html-minifier-next 4.2.0 → 4.3.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 [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.
7
+ The project was 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 backwards-compatible with both. The project was set up because as of 2025, both HTML Minifier Terser and HTML Minifier had been unmaintained for a few years. As the project seems maintainable [to me, [Jens](https://meiert.com/)]—even more so with community support—, it’s being [updated, extended, and documented](https://github.com/j9t/html-minifier-next/blob/main/CHANGELOG.md) further in this place.
8
8
 
9
9
  ## Installation
10
10
 
@@ -114,6 +114,7 @@ Options can be used in config files (camelCase) or via CLI flags (kebab-case wit
114
114
  | `collapseInlineTagWhitespace`<br>`--collapse-inline-tag-whitespace` | Don’t leave any spaces between `display: inline;` elements when collapsing—use with `collapseWhitespace: true` | `false` |
115
115
  | `collapseWhitespace`<br>`--collapse-whitespace` | [Collapse whitespace that contributes to text nodes in a document tree](https://perfectionkills.com/experimenting-with-html-minifier#collapse_whitespace) | `false` |
116
116
  | `conservativeCollapse`<br>`--conservative-collapse` | Always collapse to 1 space (never remove it entirely)—use with `collapseWhitespace: true` | `false` |
117
+ | `continueOnMinifyError`<br>`--no-continue-on-minify-error` | Continue on minification errors; when `false`, minification errors throw and abort processing | `true` |
117
118
  | `continueOnParseError`<br>`--continue-on-parse-error` | [Handle parse errors](https://html.spec.whatwg.org/multipage/parsing.html#parse-errors) instead of aborting | `false` |
118
119
  | `customAttrAssign`<br>`--custom-attr-assign` | Arrays of regexes that allow to support custom attribute assign expressions (e.g., `<div flex?="{{mode != cover}}"></div>`) | `[]` |
119
120
  | `customAttrCollapse`<br>`--custom-attr-collapse` | Regex that specifies custom attribute to strip newlines from (e.g., `/ng-class/`) | |
@@ -178,10 +179,10 @@ const result = await minify(html, {
178
179
 
179
180
  Available Lightning CSS options when passed as an object:
180
181
 
181
- * `targets`: Browser targets for vendor prefix optimization (e.g., `{ chrome: 95, firefox: 90 }`)
182
- * `unusedSymbols`: Array of class names, IDs, keyframe names, and CSS variables to remove
183
- * `errorRecovery`: Boolean to skip invalid rules instead of throwing errors (disabled in Lightning CSS, but enabled by default in HMN)
184
- * `sourceMap`: Boolean to generate source maps
182
+ * `targets`: Browser targets for vendor prefix optimization (e.g., `{ chrome: 95, firefox: 90 }`).
183
+ * `unusedSymbols`: Array of class names, IDs, keyframe names, and CSS variables to remove.
184
+ * `errorRecovery`: Boolean to skip invalid rules instead of throwing errors. This is disabled by default in Lightning CSS, but enabled in HMN when the `continueOnMinifyError` option is set to `true` (the default). Explicitly setting `errorRecovery` in `minifyCSS` options will override this automatic behavior.
185
+ * `sourceMap`: Boolean to generate source maps.
185
186
 
186
187
  For advanced usage, you can also pass a function:
187
188
 
@@ -202,23 +203,23 @@ How does HTML Minifier Next compare to other solutions, like [minimize](https://
202
203
  | Site | Original Size (KB) | HTML Minifier Next | minimize | html­compressor.com | htmlnano | minify-html |
203
204
  | --- | --- | --- | --- | --- | --- | --- |
204
205
  | [A List Apart](https://alistapart.com/) | 62 | **52** | 58 | 56 | 54 | 55 |
205
- | [Amazon](https://www.amazon.com/) | 206 | **195** | 203 | 200 | 196 | n/a |
206
- | [Apple](https://www.apple.com/) | 153 | **116** | 140 | 140 | 133 | 138 |
207
- | [BBC](https://www.bbc.co.uk/) | 590 | **534** | 585 | n/a | 553 | 555 |
208
- | [CSS-Tricks](https://css-tricks.com/) | 165 | **124** | 151 | 147 | 129 | 146 |
209
- | [ECMAScript](https://tc39.es/ecma262/) | 7238 | **6342** | 6614 | n/a | 6561 | 6567 |
210
- | [EFF](https://www.eff.org/) | 57 | **48** | 52 | 51 | 51 | 49 |
211
- | [FAZ](https://www.faz.net/aktuell/) | 1847 | 1722 | 1762 | n/a | **1628** | n/a |
212
- | [Frontend Dogma](https://frontenddogma.com/) | 219 | **211** | 237 | 218 | 232 | 218 |
213
- | [Google](https://www.google.com/) | 18 | **16** | 18 | 18 | 17 | n/a |
214
- | [Ground News](https://ground.news/) | 1709 | **1463** | 1696 | n/a | 1567 | n/a |
206
+ | [Amazon](https://www.amazon.com/) | 822 | **735** | 806 | n/a | n/a | n/a |
207
+ | [Apple](https://www.apple.com/) | 210 | **166** | 195 | 192 | 186 | 191 |
208
+ | [BBC](https://www.bbc.co.uk/) | 698 | **632** | 692 | n/a | 655 | 656 |
209
+ | [CSS-Tricks](https://css-tricks.com/) | 163 | **124** | 149 | 146 | 127 | 145 |
210
+ | [ECMAScript](https://tc39.es/ecma262/) | 7238 | **6342** | 6615 | n/a | 6561 | 6567 |
211
+ | [EFF](https://www.eff.org/) | 54 | **46** | 49 | 49 | 49 | 47 |
212
+ | [FAZ](https://www.faz.net/aktuell/) | 1860 | **1737** | 1775 | n/a | n/a | 1779 |
213
+ | [Frontend Dogma](https://frontenddogma.com/) | 218 | **209** | 235 | 216 | 230 | 217 |
214
+ | [Google](https://www.google.com/) | 18 | **17** | 18 | 18 | **17** | n/a |
215
+ | [Ground News](https://ground.news/) | 1827 | **1585** | 1814 | n/a | 1679 | n/a |
215
216
  | [HTML](https://html.spec.whatwg.org/multipage/) | 149 | **147** | 155 | 148 | 153 | 149 |
216
- | [Leanpub](https://leanpub.com/) | 1424 | **1190** | 1418 | n/a | 1197 | n/a |
217
+ | [Leanpub](https://leanpub.com/) | 1161 | **974** | 1155 | n/a | 981 | n/a |
217
218
  | [Mastodon](https://mastodon.social/explore) | 35 | **26** | 34 | 34 | 30 | 33 |
218
219
  | [MDN](https://developer.mozilla.org/en-US/) | 107 | **62** | 67 | 68 | 64 | n/a |
219
- | [Middle East Eye](https://www.middleeasteye.net/) | 224 | **197** | 203 | 204 | 204 | 201 |
220
- | [SitePoint](https://www.sitepoint.com/) | 536 | **405** | 532 | n/a | 474 | 516 |
221
- | [United Nations](https://www.un.org/en/) | 151 | **113** | 130 | 123 | 121 | 125 |
220
+ | [Middle East Eye](https://www.middleeasteye.net/) | 223 | **196** | 203 | 203 | 203 | 200 |
221
+ | [SitePoint](https://www.sitepoint.com/) | 494 | **353** | 491 | n/a | 429 | 474 |
222
+ | [United Nations](https://www.un.org/en/) | 152 | **113** | 131 | 124 | 122 | 126 |
222
223
  | [W3C](https://www.w3.org/) | 50 | **36** | 41 | 39 | 39 | 39 |
223
224
 
224
225
  ## Examples
package/cli.js CHANGED
@@ -121,6 +121,7 @@ const mainOptions = {
121
121
  collapseInlineTagWhitespace: 'Don’t leave any spaces between “display: inline;” elements when collapsing—use with “collapseWhitespace=true”',
122
122
  collapseWhitespace: 'Collapse whitespace that contributes to text nodes in a document tree',
123
123
  conservativeCollapse: 'Always collapse to 1 space (never remove it entirely)—use with “collapseWhitespace=true”',
124
+ continueOnMinifyError: 'Continue on minification errors',
124
125
  continueOnParseError: 'Handle parse errors instead of aborting',
125
126
  customAttrAssign: ['Arrays of regexes that allow to support custom attribute assign expressions (e.g., “<div flex?="{{mode != cover}}"></div>”)', parseJSONRegExpArray],
126
127
  customAttrCollapse: ['Regex that specifies custom attribute to strip newlines from (e.g., /ng-class/)', parseRegExp],
@@ -167,7 +168,7 @@ mainOptionKeys.forEach(function (key) {
167
168
  key = key === 'minifyURLs' ? '--minify-urls' : '--' + paramCase(key);
168
169
  key += option[1] === parseJSON ? ' [value]' : ' <value>';
169
170
  program.option(key, option[0], option[1]);
170
- } else if (~['html5', 'includeAutoGeneratedTags'].indexOf(key)) {
171
+ } else if (~['html5', 'includeAutoGeneratedTags', 'continueOnMinifyError'].indexOf(key)) {
171
172
  program.option('--no-' + paramCase(key), option);
172
173
  } else {
173
174
  program.option('--' + paramCase(key), option);
@@ -180,8 +181,8 @@ program.option('-d --dry', 'Dry run: process and report statistics without writi
180
181
  function readFile(file) {
181
182
  try {
182
183
  return fs.readFileSync(file, { encoding: 'utf8' });
183
- } catch (e) {
184
- fatal('Cannot read ' + file + '\n' + e.message);
184
+ } catch (err) {
185
+ fatal('Cannot read ' + file + '\n' + err.message);
185
186
  }
186
187
  }
187
188
 
@@ -196,7 +197,7 @@ async function loadConfigFromPath(configPath) {
196
197
  // Try JSON first
197
198
  try {
198
199
  return JSON.parse(data);
199
- } catch (je) {
200
+ } catch (jsonErr) {
200
201
  const abs = path.resolve(configPath);
201
202
 
202
203
  // Try CJS require
@@ -204,13 +205,13 @@ async function loadConfigFromPath(configPath) {
204
205
  const result = require(abs);
205
206
  // Handle ESM interop: if `require()` loads an ESM file, it may return `{__esModule: true, default: …}`
206
207
  return (result && result.__esModule && result.default) ? result.default : result;
207
- } catch (ne) {
208
+ } catch (cjsErr) {
208
209
  // Try ESM import
209
210
  try {
210
211
  const mod = await import(pathToFileURL(abs).href);
211
212
  return mod.default || mod;
212
- } catch (ee) {
213
- fatal('Cannot read the specified config file.\nAs JSON: ' + je.message + '\nAs CJS: ' + ne.message + '\nAs ESM: ' + ee.message);
213
+ } catch (esmErr) {
214
+ fatal('Cannot read the specified config file.\nAs JSON: ' + jsonErr.message + '\nAs CJS: ' + cjsErr.message + '\nAs ESM: ' + esmErr.message);
214
215
  }
215
216
  }
216
217
  }
@@ -307,8 +308,8 @@ program.option('--file-ext <extensions>', 'Specify file extension(s) to process
307
308
  let minified;
308
309
  try {
309
310
  minified = await minify(data, createOptions());
310
- } catch (e) {
311
- fatal('Minification error on ' + inputFile + '\n' + e.message);
311
+ } catch (err) {
312
+ fatal('Minification error on ' + inputFile + '\n' + err.message);
312
313
  }
313
314
 
314
315
  const stats = calculateStats(data, minified);
@@ -466,8 +467,8 @@ program.option('--file-ext <extensions>', 'Specify file extension(s) to process
466
467
 
467
468
  try {
468
469
  minified = await minify(content, minifierOptions);
469
- } catch (e) {
470
- fatal('Minification error:\n' + e.message);
470
+ } catch (err) {
471
+ fatal('Minification error:\n' + err.message);
471
472
  }
472
473
 
473
474
  const stats = calculateStats(content, minified);
@@ -835,6 +835,9 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
835
835
  const out = await options.minifyURLs(attrValue);
836
836
  return typeof out === 'string' ? out : attrValue;
837
837
  } catch (err) {
838
+ if (!options.continueOnMinifyError) {
839
+ throw err;
840
+ }
838
841
  options.log && options.log(err);
839
842
  return attrValue;
840
843
  }
@@ -867,6 +870,9 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
867
870
  const out = await options.minifyURLs(url);
868
871
  return (typeof out === 'string' ? out : url) + descriptor;
869
872
  } catch (err) {
873
+ if (!options.continueOnMinifyError) {
874
+ throw err;
875
+ }
870
876
  options.log && options.log(err);
871
877
  return url + descriptor;
872
878
  }
@@ -1221,6 +1227,7 @@ const processOptions = (inputOptions) => {
1221
1227
  },
1222
1228
  canCollapseWhitespace,
1223
1229
  canTrimWhitespace,
1230
+ continueOnMinifyError: true,
1224
1231
  html5: true,
1225
1232
  ignoreCustomComments: [
1226
1233
  /^!/,
@@ -1266,6 +1273,9 @@ const processOptions = (inputOptions) => {
1266
1273
  const out = await options.minifyURLs(url);
1267
1274
  return prefix + quote + (typeof out === 'string' ? out : url) + quote + suffix;
1268
1275
  } catch (err) {
1276
+ if (!options.continueOnMinifyError) {
1277
+ throw err;
1278
+ }
1269
1279
  options.log && options.log(err);
1270
1280
  return match;
1271
1281
  }
@@ -1279,7 +1289,7 @@ const processOptions = (inputOptions) => {
1279
1289
  filename: 'input.css',
1280
1290
  code: Buffer.from(inputCSS),
1281
1291
  minify: true,
1282
- errorRecovery: true,
1292
+ errorRecovery: !!options.continueOnMinifyError,
1283
1293
  ...lightningCssOptions
1284
1294
  });
1285
1295
 
@@ -1303,6 +1313,9 @@ const processOptions = (inputOptions) => {
1303
1313
 
1304
1314
  return outputCSS;
1305
1315
  } catch (err) {
1316
+ if (!options.continueOnMinifyError) {
1317
+ throw err;
1318
+ }
1306
1319
  options.log && options.log(err);
1307
1320
  return text;
1308
1321
  }
@@ -1328,8 +1341,11 @@ const processOptions = (inputOptions) => {
1328
1341
  try {
1329
1342
  const result = await terser.minify(code, terserOptions);
1330
1343
  return result.code.replace(/;$/, '');
1331
- } catch (error) {
1332
- options.log(error);
1344
+ } catch (err) {
1345
+ if (!options.continueOnMinifyError) {
1346
+ throw err;
1347
+ }
1348
+ options.log && options.log(err);
1333
1349
  return text;
1334
1350
  }
1335
1351
  };
@@ -1350,7 +1366,10 @@ const processOptions = (inputOptions) => {
1350
1366
  try {
1351
1367
  return RelateURL.relate(text, relateUrlOptions);
1352
1368
  } catch (err) {
1353
- options.log(err);
1369
+ if (!options.continueOnMinifyError) {
1370
+ throw err;
1371
+ }
1372
+ options.log && options.log(err);
1354
1373
  return text;
1355
1374
  }
1356
1375
  };
@@ -2061,6 +2080,13 @@ var htmlminifier = { minify };
2061
2080
  *
2062
2081
  * Default: `false`
2063
2082
  *
2083
+ * @prop {boolean} [continueOnMinifyError]
2084
+ * When set to `false`, minification errors may throw.
2085
+ * By default, the minifier will attempt to recover from minification
2086
+ * errors, or ignore them and preserve the original content.
2087
+ *
2088
+ * Default: `true`
2089
+ *
2064
2090
  * @prop {boolean} [continueOnParseError]
2065
2091
  * When true, the parser will attempt to continue on recoverable parse
2066
2092
  * errors. Otherwise, parsing errors may throw.
@@ -39888,6 +39888,9 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
39888
39888
  const out = await options.minifyURLs(attrValue);
39889
39889
  return typeof out === 'string' ? out : attrValue;
39890
39890
  } catch (err) {
39891
+ if (!options.continueOnMinifyError) {
39892
+ throw err;
39893
+ }
39891
39894
  options.log && options.log(err);
39892
39895
  return attrValue;
39893
39896
  }
@@ -39920,6 +39923,9 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
39920
39923
  const out = await options.minifyURLs(url);
39921
39924
  return (typeof out === 'string' ? out : url) + descriptor;
39922
39925
  } catch (err) {
39926
+ if (!options.continueOnMinifyError) {
39927
+ throw err;
39928
+ }
39923
39929
  options.log && options.log(err);
39924
39930
  return url + descriptor;
39925
39931
  }
@@ -40274,6 +40280,7 @@ const processOptions = (inputOptions) => {
40274
40280
  },
40275
40281
  canCollapseWhitespace,
40276
40282
  canTrimWhitespace,
40283
+ continueOnMinifyError: true,
40277
40284
  html5: true,
40278
40285
  ignoreCustomComments: [
40279
40286
  /^!/,
@@ -40319,6 +40326,9 @@ const processOptions = (inputOptions) => {
40319
40326
  const out = await options.minifyURLs(url);
40320
40327
  return prefix + quote + (typeof out === 'string' ? out : url) + quote + suffix;
40321
40328
  } catch (err) {
40329
+ if (!options.continueOnMinifyError) {
40330
+ throw err;
40331
+ }
40322
40332
  options.log && options.log(err);
40323
40333
  return match;
40324
40334
  }
@@ -40332,7 +40342,7 @@ const processOptions = (inputOptions) => {
40332
40342
  filename: 'input.css',
40333
40343
  code: Buffer.from(inputCSS),
40334
40344
  minify: true,
40335
- errorRecovery: true,
40345
+ errorRecovery: !!options.continueOnMinifyError,
40336
40346
  ...lightningCssOptions
40337
40347
  });
40338
40348
 
@@ -40356,6 +40366,9 @@ const processOptions = (inputOptions) => {
40356
40366
 
40357
40367
  return outputCSS;
40358
40368
  } catch (err) {
40369
+ if (!options.continueOnMinifyError) {
40370
+ throw err;
40371
+ }
40359
40372
  options.log && options.log(err);
40360
40373
  return text;
40361
40374
  }
@@ -40381,8 +40394,11 @@ const processOptions = (inputOptions) => {
40381
40394
  try {
40382
40395
  const result = await minify$1(code, terserOptions);
40383
40396
  return result.code.replace(/;$/, '');
40384
- } catch (error) {
40385
- options.log(error);
40397
+ } catch (err) {
40398
+ if (!options.continueOnMinifyError) {
40399
+ throw err;
40400
+ }
40401
+ options.log && options.log(err);
40386
40402
  return text;
40387
40403
  }
40388
40404
  };
@@ -40403,7 +40419,10 @@ const processOptions = (inputOptions) => {
40403
40419
  try {
40404
40420
  return RelateURL.relate(text, relateUrlOptions);
40405
40421
  } catch (err) {
40406
- options.log(err);
40422
+ if (!options.continueOnMinifyError) {
40423
+ throw err;
40424
+ }
40425
+ options.log && options.log(err);
40407
40426
  return text;
40408
40427
  }
40409
40428
  };
@@ -41114,6 +41133,13 @@ var htmlminifier = { minify };
41114
41133
  *
41115
41134
  * Default: `false`
41116
41135
  *
41136
+ * @prop {boolean} [continueOnMinifyError]
41137
+ * When set to `false`, minification errors may throw.
41138
+ * By default, the minifier will attempt to recover from minification
41139
+ * errors, or ignore them and preserve the original content.
41140
+ *
41141
+ * Default: `true`
41142
+ *
41117
41143
  * @prop {boolean} [continueOnParseError]
41118
41144
  * When true, the parser will attempt to continue on recoverable parse
41119
41145
  * errors. Otherwise, parsing errors may throw.
@@ -73,6 +73,14 @@ export type MinifierOptions = {
73
73
  * Default: `false`
74
74
  */
75
75
  conservativeCollapse?: boolean;
76
+ /**
77
+ * When set to `false`, minification errors may throw.
78
+ * By default, the minifier will attempt to recover from minification
79
+ * errors, or ignore them and preserve the original content.
80
+ *
81
+ * Default: `true`
82
+ */
83
+ continueOnMinifyError?: boolean;
76
84
  /**
77
85
  * When true, the parser will attempt to continue on recoverable parse
78
86
  * errors. Otherwise, parsing errors may throw.
@@ -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,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"}
1
+ {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAs8CO,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;;;;;;;;4BAOP,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
@@ -22,10 +22,10 @@
22
22
  "@rollup/plugin-node-resolve": "^16.0.3",
23
23
  "@rollup/plugin-terser": "^0.4.4",
24
24
  "eslint": "^9.39.1",
25
- "rollup": "^4.52.5",
25
+ "rollup": "^4.53.2",
26
26
  "rollup-plugin-polyfill-node": "^0.13.0",
27
27
  "typescript": "^5.9.3",
28
- "vite": "^7.1.12"
28
+ "vite": "^7.2.2"
29
29
  },
30
30
  "exports": {
31
31
  ".": {
@@ -84,5 +84,5 @@
84
84
  "test:watch": "node --test --watch tests/*.spec.js"
85
85
  },
86
86
  "type": "module",
87
- "version": "4.2.0"
87
+ "version": "4.3.0"
88
88
  }
@@ -305,6 +305,9 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
305
305
  const out = await options.minifyURLs(attrValue);
306
306
  return typeof out === 'string' ? out : attrValue;
307
307
  } catch (err) {
308
+ if (!options.continueOnMinifyError) {
309
+ throw err;
310
+ }
308
311
  options.log && options.log(err);
309
312
  return attrValue;
310
313
  }
@@ -337,6 +340,9 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
337
340
  const out = await options.minifyURLs(url);
338
341
  return (typeof out === 'string' ? out : url) + descriptor;
339
342
  } catch (err) {
343
+ if (!options.continueOnMinifyError) {
344
+ throw err;
345
+ }
340
346
  options.log && options.log(err);
341
347
  return url + descriptor;
342
348
  }
@@ -691,6 +697,7 @@ const processOptions = (inputOptions) => {
691
697
  },
692
698
  canCollapseWhitespace,
693
699
  canTrimWhitespace,
700
+ continueOnMinifyError: true,
694
701
  html5: true,
695
702
  ignoreCustomComments: [
696
703
  /^!/,
@@ -736,6 +743,9 @@ const processOptions = (inputOptions) => {
736
743
  const out = await options.minifyURLs(url);
737
744
  return prefix + quote + (typeof out === 'string' ? out : url) + quote + suffix;
738
745
  } catch (err) {
746
+ if (!options.continueOnMinifyError) {
747
+ throw err;
748
+ }
739
749
  options.log && options.log(err);
740
750
  return match;
741
751
  }
@@ -749,7 +759,7 @@ const processOptions = (inputOptions) => {
749
759
  filename: 'input.css',
750
760
  code: Buffer.from(inputCSS),
751
761
  minify: true,
752
- errorRecovery: true,
762
+ errorRecovery: !!options.continueOnMinifyError,
753
763
  ...lightningCssOptions
754
764
  });
755
765
 
@@ -773,6 +783,9 @@ const processOptions = (inputOptions) => {
773
783
 
774
784
  return outputCSS;
775
785
  } catch (err) {
786
+ if (!options.continueOnMinifyError) {
787
+ throw err;
788
+ }
776
789
  options.log && options.log(err);
777
790
  return text;
778
791
  }
@@ -798,8 +811,11 @@ const processOptions = (inputOptions) => {
798
811
  try {
799
812
  const result = await terser(code, terserOptions);
800
813
  return result.code.replace(/;$/, '');
801
- } catch (error) {
802
- options.log(error);
814
+ } catch (err) {
815
+ if (!options.continueOnMinifyError) {
816
+ throw err;
817
+ }
818
+ options.log && options.log(err);
803
819
  return text;
804
820
  }
805
821
  };
@@ -820,7 +836,10 @@ const processOptions = (inputOptions) => {
820
836
  try {
821
837
  return RelateURL.relate(text, relateUrlOptions);
822
838
  } catch (err) {
823
- options.log(err);
839
+ if (!options.continueOnMinifyError) {
840
+ throw err;
841
+ }
842
+ options.log && options.log(err);
824
843
  return text;
825
844
  }
826
845
  };
@@ -1531,6 +1550,13 @@ export default { minify };
1531
1550
  *
1532
1551
  * Default: `false`
1533
1552
  *
1553
+ * @prop {boolean} [continueOnMinifyError]
1554
+ * When set to `false`, minification errors may throw.
1555
+ * By default, the minifier will attempt to recover from minification
1556
+ * errors, or ignore them and preserve the original content.
1557
+ *
1558
+ * Default: `true`
1559
+ *
1534
1560
  * @prop {boolean} [continueOnParseError]
1535
1561
  * When true, the parser will attempt to continue on recoverable parse
1536
1562
  * errors. Otherwise, parsing errors may throw.