html-minifier-next 7.5.3 → 7.6.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
@@ -41,7 +41,7 @@ Use `npx html-minifier-next --help` to check all available options:
41
41
  | `--file-ext <extensions>`, `-f <extensions>` | Specify file extension(s) to process (comma-separated, overrides config file setting); defaults to `html,htm,shtml,shtm`; use `*` for all files | `--file-ext=html,php`, `--file-ext='*'` |
42
42
  | `--preset <name>`, `-p <name>` | Use a preset configuration (conservative or comprehensive) | `--preset=conservative` |
43
43
  | `--config-file <file>`, `-c <file>` | Use a configuration file (defaults to html-minifier-next.config.json in the working directory, if present) | `--config-file=path/to/config.json` |
44
- | `--verbose`, `-v` | Show detailed processing information (active options, file statistics) | `npx html-minifier-next --input-dir=src --output-dir=dist --verbose --collapse-whitespace` |
44
+ | `--verbose`, `-v` | Show detailed processing information (active options, file statistics, and minifier warnings) | `npx html-minifier-next --input-dir=src --output-dir=dist --verbose --collapse-whitespace` |
45
45
  | `--dry`, `-d` | Dry run: Process and report statistics without writing output | `npx html-minifier-next input.html --dry --collapse-whitespace` |
46
46
 
47
47
  ### Configuration file
@@ -91,7 +91,7 @@ const result = await minify('<p title="example" id="moo">foo</p>', {
91
91
  removeAttributeQuotes: true,
92
92
  removeOptionalTags: true
93
93
  });
94
- console.log(result); // “<p title=example id=moo>foo”
94
+ console.log(result); // `<p title=example id=moo>foo`
95
95
  ```
96
96
 
97
97
  See [the original blog post](https://perfectionkills.com/experimenting-with-html-minifier/) for details of [how it works](https://perfectionkills.com/experimenting-with-html-minifier/#how_it_works), [descriptions of most options](https://perfectionkills.com/experimenting-with-html-minifier/#options), [testing results](https://perfectionkills.com/experimenting-with-html-minifier/#field_testing), and [conclusions](https://perfectionkills.com/experimenting-with-html-minifier/#cost_and_benefits).
@@ -173,6 +173,7 @@ Options can be used in config files (camelCase) or via CLI flags (kebab-case wit
173
173
  | `removeOptionalTags`<br>`--remove-optional-tags` | [Remove optional tags](https://perfectionkills.com/experimenting-with-html-minifier/#remove_optional_tags) | `false` |
174
174
  | `removeRedundantAttributes`<br>`--remove-redundant-attributes` | [Remove attributes when value matches default](https://meiert.com/blog/optional-html/#toc-attribute-values) | `false` |
175
175
  | `removeTagWhitespace`<br>`--remove-tag-whitespace` | Remove space between attributes whenever possible; **note that this will result in invalid HTML** | `false` |
176
+ | `removeUnusedCSS`<br>`--remove-unused-css` | [Remove unused CSS rules](#unused-css-removal) from `style` elements; requires `minifyCSS`; **note that this can change how a document renders** | `false` (could be `true`, `{ safelist, scripts }`) |
176
177
  | `sortAttributes`<br>`--sort-attributes` | [Sort attributes by frequency](#sorting-attributes-and-style-classes) | `false` |
177
178
  | `sortClassNames`<br>`--sort-class-names` | [Sort style classes by frequency](#sorting-attributes-and-style-classes) | `false` |
178
179
  | `trimCustomFragments`<br>`--trim-custom-fragments` | Trim whitespace around custom fragments (`ignoreCustomFragments`) | `false` |
@@ -186,7 +187,7 @@ A few options take functions and are therefore only available programmatically,
186
187
  | --- | --- | --- |
187
188
  | `canCollapseWhitespace` | `Function(tag, attrs, defaultFn)` that determines whether whitespace inside an element can be collapsed—override to protect additional elements, delegating to `defaultFn` for the rest | Built-in handling (protects `pre`, `textarea`, etc.) |
188
189
  | `canTrimWhitespace` | `Function(tag, attrs, defaultFn)` that determines whether leading and trailing whitespace around an element may be trimmed | Built-in handling |
189
- | `log` | `Function(message)` called with warnings and errors, including minification errors swallowed by `continueOnMinifyError` (e.g., pass `console.error` to surface them) | No-op (errors are silent) |
190
+ | `log` | `Function(message)` called with warnings and errors, including minification errors swallowed by `continueOnMinifyError` (e.g., pass `console.error` to surface them); the CLI wires this up under `--verbose` and `--dry` | No-op (errors are silent) |
190
191
 
191
192
  ### Sorting attributes and style classes
192
193
 
@@ -216,7 +217,7 @@ Available Lightning CSS options when passed as an object:
216
217
 
217
218
  * `targets`: Browser targets for vendor prefix optimization (e.g., `{ chrome: 95, firefox: 90 }`).
218
219
  * `unusedSymbols`: Array of class names, IDs, keyframe names, and CSS variables to remove.
219
- * `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.
220
+ * `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. What Lightning CSS takes issue with is reported through [the `log` hook](#api-only-options)—it drops some of it (`@property` with an invalid `syntax`) and passes the rest through (an unknown at-rule), so that a dropped rule does not go unnoticed. Every document is reported on separately.
220
221
  * `sourceMap`: Boolean to generate source maps.
221
222
 
222
223
  For advanced usage, you can also pass a function:
@@ -231,6 +232,44 @@ const result = await minify(html, {
231
232
  });
232
233
  ```
233
234
 
235
+ ### Unused CSS removal
236
+
237
+ `removeUnusedCSS` removes rules from `style` elements whose class or ID selectors the document doesn’t reference. It requires `minifyCSS`, because the removal runs through Lightning CSS—passing `minifyCSS` a function of your own replaces that step, so the removal does not apply, either. Both cases are reported through [the `log` hook](#api-only-options). It does not touch `style` or `media` attributes.
238
+
239
+ ```js
240
+ const result = await minify(html, {
241
+ minifyCSS: true,
242
+ removeUnusedCSS: true
243
+ });
244
+ ```
245
+
246
+ Symbols are considered used when they appear
247
+
248
+ * in a `class` or `id` attribute,
249
+ * in an attribute that references an ID (`for`, `headers`, `list`, `popovertarget`, `aria-controls`, and similar),
250
+ * in a same-document fragment URL, as `href="#main"`, `<use href="#icon">`, or `usemap="#map"`, and in a `url(#gradient)` reference from any attribute,
251
+ * anywhere in a `data-*` attribute value, or
252
+ * anywhere inside an inline `script` element, unless `scripts` is set to `false`.
253
+
254
+ Names carrying characters that end a CSS identifier—`md:flex`, `w-1/2`, `p-[3px]`—are matched as whole tokens, so utility-CSS class names survive whether they come from markup, a `data-*` value, or a string in an inline script.
255
+
256
+ **Class names that only appear in external scripts cannot be detected.** A minifier sees one document, not the DOM that scripts later build from it, so a class added by `bundle.js` looks exactly like a class nobody uses. List those under `safelist`, as strings or regular expressions:
257
+
258
+ ```js
259
+ const result = await minify(html, {
260
+ minifyCSS: true,
261
+ removeUnusedCSS: {
262
+ safelist: ['is-open', /^js-/],
263
+ // Set to `false` to also drop rules only referenced from inline scripts
264
+ scripts: true
265
+ }
266
+ });
267
+ ```
268
+
269
+ Names used by `@keyframes` and `@counter-style` rules are not removed, even when no element carries them as a class or ID, since those at-rules are referenced from CSS rather than from markup.
270
+
271
+ Values that cannot be honored—a `safelist` that isn’t an array, an entry that is neither a string nor a regular expression, a misspelled key—are reported through the `log` hook.
272
+
234
273
  ### JavaScript minification
235
274
 
236
275
  When `minifyJS` is set to `true`, HTML Minifier Next uses [Terser](https://terser.org/) by default to minify JavaScript in `<script>` elements and event attributes.
package/cli.js CHANGED
@@ -141,6 +141,7 @@ const typeParsers = {
141
141
  regexp: parseRegExp,
142
142
  regexpArray: parseJSONRegExpArray,
143
143
  json: parseJSON,
144
+ jsonObject: parseJSON,
144
145
  jsonArray: parseJSONArray,
145
146
  string: parseString,
146
147
  int: (key) => parseValidInt(key)
@@ -165,7 +166,7 @@ mainOptionKeys.forEach(function (key) {
165
166
  program.addOption(new Option('--no-' + flag, 'Disable --' + flag).hideHelp());
166
167
  }
167
168
  } else {
168
- const cliFlag = '--' + flag + (type === 'json' ? ' [value]' : ' <value>');
169
+ const cliFlag = '--' + flag + (type === 'json' || type === 'jsonObject' ? ' [value]' : ' <value>');
169
170
  const parser = type === 'int' ? typeParsers.int(key) : typeParsers[type];
170
171
  program.option(cliFlag, description, parser);
171
172
  }
@@ -244,7 +245,7 @@ function normalizeConfig(config) {
244
245
  // Warn about unrecognized config keys—catches typos as well as options removed in earlier versions
245
246
  Object.keys(normalized).forEach(function (key) {
246
247
  if (!Object.hasOwn(optionDefinitions, key) && !CONFIG_KEYS_EXTRA.has(key)) {
247
- console.error(`Ignoring unknown or deprecated config option “${key}” (see \`--help\` or README for available options)`);
248
+ console.error(`Ignoring unknown or deprecated config option \`${key}\` (see \`--help\` or README for available options)`);
248
249
  }
249
250
  });
250
251
 
@@ -282,9 +283,9 @@ function normalizeConfig(config) {
282
283
  let config = {};
283
284
  program.option('-z, --zero', 'Minify all HTML files in the current folder and its subfolders in place (except node_modules), using comprehensive settings (standalone—flag is ignored when combined with other options)');
284
285
  program.option('-I --input-dir <dir>', 'Specify an input directory');
285
- program.option('-X --ignore-dir <patterns>', 'Exclude directories—relative to input directory—from processing (comma-separated), e.g., “libs” or “libs,vendor,node_modules”');
286
+ program.option('-X --ignore-dir <patterns>', 'Exclude directories—relative to input directory—from processing (comma-separated), e.g., `libs` or `libs,vendor,node_modules`');
286
287
  program.option('-O --output-dir <dir>', 'Specify an output directory');
287
- program.option('-f --file-ext <extensions>', 'Specify file extension(s) to process (comma-separated); defaults to “html,htm,shtml,shtm”; use “*” for all files');
288
+ program.option('-f --file-ext <extensions>', 'Specify file extension(s) to process (comma-separated); defaults to `html,htm,shtml,shtm`; use `*` for all files');
288
289
  program.option('-p --preset <name>', `Use a preset configuration (${getPresetNames().join(', ')})`);
289
290
  program.option('-c --config-file <file>', 'Use config file');
290
291
  program.version(pkg.version, '-V, --version', 'Output the version number');
@@ -399,7 +400,7 @@ program.helpOption('-h, --help', 'Display help for command');
399
400
  } else {
400
401
  const configFileDefault = CONFIG_FILES_DEFAULT.find(name => fs.existsSync(path.resolve(name)));
401
402
  if (configFileDefault) {
402
- console.error(`Using config file “${configFileDefault}”`);
403
+ console.error(`Using config file ${configFileDefault}`);
403
404
  config = normalizeConfig(await loadConfigFromPath(configFileDefault));
404
405
  }
405
406
  }
@@ -438,6 +439,26 @@ program.helpOption('-h, --help', 'Display help for command');
438
439
  }
439
440
  });
440
441
 
442
+ // 4. Surface minifier diagnostics when verbose
443
+ if (programOptions.verbose || programOptions.dry) {
444
+ options.log = message => {
445
+ // The hook carries the minifier’s per-call timing as well, which the run's own
446
+ // per-file statistics already cover
447
+ if (typeof message === 'string' && message.startsWith('minified in: ')) {
448
+ return;
449
+ }
450
+ // Only `continueOnMinifyError` passes `Error` objects, always after leaving the
451
+ // offending content unminified—so say that
452
+ if (message instanceof Error) {
453
+ console.error(` ${MARK_WARNING}Warning: Minification failed, content left as-is: ${message.message || message}${MARK_RESET}`);
454
+ } else if (String(message).startsWith('Warning: ') || String(message).startsWith('HTML Minifier Next: ')) {
455
+ console.error(` ${MARK_WARNING}${message}${MARK_RESET}`);
456
+ } else {
457
+ console.error(` ${message}`);
458
+ }
459
+ };
460
+ }
461
+
441
462
  return options;
442
463
  }
443
464
 
@@ -881,7 +902,7 @@ program.helpOption('-h, --help', 'Display help for command');
881
902
  for (const file of capturedFiles) {
882
903
  const ext = path.extname(file).replace(/^\./, '').toLowerCase();
883
904
  if (EXTENSIONS_NON_HTML.has(ext)) {
884
- console.error(`${MARK_WARNING}Warning: “${path.basename(file)}” does not appear to be an HTML file—HTML Minifier Next processes CSS, JavaScript, and SVG only when embedded in HTML. The output may be incomplete or broken.${MARK_RESET}`);
905
+ console.error(`${MARK_WARNING}Warning: ${path.basename(file)} does not appear to be an HTML file—HTML Minifier Next processes CSS, JavaScript, and SVG only when embedded in HTML. The output may be incomplete or broken.${MARK_RESET}`);
885
906
  }
886
907
  }
887
908
 
@@ -421,6 +421,24 @@ export type MinifierOptions = {
421
421
  * Default: `false`
422
422
  */
423
423
  removeTagWhitespace?: boolean;
424
+ /**
425
+ * **Note that this can change how a document renders!**
426
+ *
427
+ * Remove rules from `style` elements whose class or ID selectors the document
428
+ * never references. Requires `minifyCSS` (removal runs through Lightning CSS)
429
+ * and has no effect on `style` or `media` attributes.
430
+ *
431
+ * Class names and IDs are collected from the markup, from `data-*` attributes,
432
+ * and—unless `scripts` is set to `false`—from inline `script` elements. Names
433
+ * that only ever appear in external scripts cannot be detected; list those
434
+ * under `safelist` (strings or regular expressions) to keep them.
435
+ *
436
+ * Default: `false`
437
+ */
438
+ removeUnusedCSS?: boolean | {
439
+ safelist?: Array<string | RegExp>;
440
+ scripts?: boolean;
441
+ };
424
442
  /**
425
443
  * When true, enables sorting of attributes. If a function is provided it
426
444
  * will be used as a custom attribute sorter, which should mutate `attrs`
@@ -1 +1 @@
1
- {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA2D/D,YAAkB,aAAa,GAI/B;IAAe,IAAI,EAAZ,MAAM,CACb;IAAgB,KAAK,AAArB,CACA,EADO,MAAM,CACb;IAAgB,KAAK,AAArB,CACA,EADO,MAAM,CACb;IAAgB,YAAY,AAA5B,CACA,EADO,MAAM,CACb;IAAgB,UAAU,AAA1B,CACA,EADO,MAAM,CACb;IAAgB,WAAW,AAA3B,CAA4B,EAArB,MAAM,CAAe;CAAA,CAAA;AAI5B,YAAkB,eAAe,GAIjC;;;;;;;IAA2G,qBAAqB,AAAhI,CAMA,EANO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO,CAMxG;;;;;;;IAA0H,iBAAiB,AAA3I,CAMA,EANO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO,CAMvH;;;;;;;;;;IAAgB,QAAQ,AAAxB,CASA,EATO,MAAM,CASb;;;;;;;;;;IAAgB,OAAO,AAAvB,CASA,EATO,MAAM,CASb;;;;;;;;;;IAAgB,QAAQ,AAAxB,CASA,EATO,MAAM,CASb;;;;;;;;IAAiB,aAAa,AAA9B,CAOC,EAPM,OAAO,CAOb;;;;;;;;;IAAiB,2BAA2B,AAA5C,CAQD,EARQ,OAAO,CAQf;;;;;;;;IAAiB,yBAAyB,AAA1C,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAiB,2BAA2B,AAA5C,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAiB,kBAAkB,AAAnC,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAiB,oBAAoB,AAArC,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAiB,qBAAqB,AAAtC,CAOA,EAPO,OAAO,CAOd;;;;;;;IAAiB,oBAAoB,AAArC,CAMA,EANO,OAAO,CAMd;;;;;;;;IAAkB,gBAAgB,AAAlC,CAOA,EAPO,MAAM,EAAE,CAOf;;;;;;IAAgB,kBAAkB,AAAlC,CAKA,EALO,MAAM,CAKb;;;;;;IAA4B,kBAAkB,AAA9C,CAKA,EALO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAKzB;;;;;;;IAAkB,qBAAqB,AAAvC,CAMA,EANO,MAAM,EAAE,CAMf;;;;;;;IAAgB,6BAA6B,AAA7C,CAMA,EANO,MAAM,CAMb;;;;;;;IAAiB,cAAc,AAA/B,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAkB,oBAAoB,AAAtC,CAOA,EAPO,MAAM,EAAE,CAOf;;;;;;;;;IAAkB,qBAAqB,AAAvC,CAQA,EARO,MAAM,EAAE,CAQf;;;;;;;IAAiB,wBAAwB,AAAzC,CAMA,EANO,OAAO,CAMd;;;;;;;IAA2B,oBAAoB,AAA/C,CAMA,EANO,SAAS,CAAC,MAAM,CAAC,CAMxB;;;;;;IAAiB,gBAAgB,AAAjC,CAKA,EALO,OAAO,CAKd;;;;;;;;IAAoC,GAAG,AAAvC,CAOA,EAPO,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAOjC;;;;;;;;IAAgB,cAAc,AAA9B,CAOA,EAPO,MAAM,CAOb;;;;;;;IAAgB,aAAa,AAA7B,CAMA,EANO,MAAM,CAMb;;;;;;;;IAAiB,YAAY,AAA7B,CAOA,EAPO,OAAO,CAOd;;;;;;;;;;IAAwK,SAAS,AAAjL,CASA,EATO,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,CASrK;;;;;;;;;;;;;;IAAqK,QAAQ,AAA7K,CAaA,EAbO,OAAO,GAAG,OAAO,QAAQ,EAAE,aAAa,GAAG;QAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAalK;;;;;;;;;;IAA2F,UAAU,AAArG,CASA,EATO,OAAO,GAAG,MAAM,GAAG;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CASxF;;;;;;;;;IAA0B,SAAS,AAAnC,CAQA,EARO,OAAO,GAAG,MAAM,CAQvB;;;;;;;IAAiB,wBAAwB,AAAzC,CAMA,EANO,OAAO,CAMd;;;;;;;;;;IAAiB,aAAa,AAA9B,CASA,EATO,OAAO,CASd;;;;;;;;IAAiB,kBAAkB,AAAnC,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAgB,MAAM,AAAtB,CAOA,EAPO,MAAM,CAOb;;;;;;;IAAiB,yBAAyB,AAA1C,CAMA,EANO,OAAO,CAMd;;;;;;;;;;IAAkB,cAAc,AAAhC,CASA,EATO,MAAM,EAAE,CASf;;;;;;;IAAoB,cAAc,AAAlC,CAMA,EANO,IAAI,GAAG,GAAG,CAMjB;;;;;;;IAAiB,qBAAqB,AAAtC,CAMA,EANO,OAAO,CAMd;;;;;;;;IAAiB,cAAc,AAA/B,CAOC,EAPM,OAAO,CAOb;;;;;;;IAAiB,2BAA2B,AAA5C,CAMD,EANQ,OAAO,CAMf;;;;;;;;;IAAgE,qBAAqB,AAArF,CAQA,EARO,OAAO,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAQ7D;;;;;;;;IAAiB,mBAAmB,AAApC,CAOA,EAPO,OAAO,CAOd;;;;;;;;;;;;;;;;;;;;;;;;;;IAAkB,yBAAyB,AAA3C,CAyBA,EAzBO,MAAM,EAAE,CAyBf;;;;;;;;IAAiB,kBAAkB,AAAnC,CAOA,EAPO,OAAO,CAOd;;;;;;;;IAAiB,yBAAyB,AAA1C,CAOA,EAPO,OAAO,CAOd;;;;;;;;;;IAAiB,mBAAmB,AAApC,CASA,EATO,OAAO,CASd;;;;;;;;;IAAmE,cAAc,AAAjF,CAQA,EARO,OAAO,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC,CAQhE;;;;;;;;;IAA+C,cAAc,AAA7D,CAQA,EARO,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAQ5C;;;;;;;;IAAiB,mBAAmB,AAApC,CAOA,EAPO,OAAO,CAOd;;;;;;;IAAiB,eAAe,AAAhC,CAKF,EALS,OAAO,CAKhB;CAAA,CAAA;AAiEE,YAAkB,UAAU,GAG5B;;;;IAAe,IAAI,EAAZ,MAAM,CACb;;;;IAAe,IAAI,EAAZ,MAAM,CACb;;;;IAAe,IAAI,EAAZ,MAAM,CACb;;;;IAAe,KAAK,EAAb,MAAM,CACf;CAAA,CAAA;AA83CD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAFhB;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,CAQhE;AA2FD;;;;GAIG;AACH,eAAO,MAAM,MAAM,UAJR,MAAM,YACN,eAAe,KACb,OAAO,CAAC,MAAM,CAmD1B,CAAC;AAIF,OAAO,EACL,OAAO,EACP,SAAS,EACT,cAAc,EACf,CAAC"}
1
+ {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ declare const RE_ESCAPE_LT: RegExp;
14
14
  declare const RE_ATTR_WS_CHECK: RegExp;
15
15
  declare const RE_ATTR_WS_COLLAPSE: RegExp;
16
16
  declare const RE_ATTR_WS_TRIM: RegExp;
17
+ declare const RE_STYLE_ELEMENT: RegExp;
17
18
  declare const inlineElementsToKeepWhitespaceAround: Set<string>;
18
19
  declare const inlineElementsToKeepWhitespaceWithin: Set<string>;
19
20
  declare const inlineElementsToKeepWhitespace: Set<string>;
@@ -94,5 +95,5 @@ declare const trailingElements: Set<string>;
94
95
  declare const htmlElements: Set<string>;
95
96
  declare const reEmptyAttribute: RegExp;
96
97
  declare const specialContentElements: Set<string>;
97
- export { RE_WS_START, RE_WS_END, RE_ALL_WS_NBSP, RE_NBSP_LEADING_GROUP, RE_NBSP_LEAD_GROUP, RE_NBSP_TRAILING_GROUP, RE_NBSP_TRAILING_STRIP, RE_EVENT_ATTR_DEFAULT, RE_CAN_REMOVE_ATTR_QUOTES, RE_TRAILING_SEMICOLON, RE_AMP_ENTITY, RE_LEGACY_ENTITIES, RE_ESCAPE_LT, RE_ATTR_WS_CHECK, RE_ATTR_WS_COLLAPSE, RE_ATTR_WS_TRIM, inlineElementsToKeepWhitespaceAround, inlineElementsToKeepWhitespaceWithin, inlineElementsToKeepWhitespace, formControlElements, generalDefaults, tagDefaults, executableScriptsMimetypes, keepScriptsMimetypes, jsonScriptTypes, isSimpleBoolean, isBooleanValue, collapsibleValues, srcsetElements, optionalStartTags, optionalEndTags, headerElements, descriptionElements, pBlockElements, pInlineElements, rubyEndTagOmission, rubyRtcEndTagOmission, optionElements, tableContentElements, tableSectionElements, cellElements, topLevelElements, compactElements, looseElements, trailingElements, htmlElements, reEmptyAttribute, specialContentElements };
98
+ export { RE_WS_START, RE_WS_END, RE_ALL_WS_NBSP, RE_NBSP_LEADING_GROUP, RE_NBSP_LEAD_GROUP, RE_NBSP_TRAILING_GROUP, RE_NBSP_TRAILING_STRIP, RE_EVENT_ATTR_DEFAULT, RE_CAN_REMOVE_ATTR_QUOTES, RE_TRAILING_SEMICOLON, RE_AMP_ENTITY, RE_LEGACY_ENTITIES, RE_ESCAPE_LT, RE_ATTR_WS_CHECK, RE_ATTR_WS_COLLAPSE, RE_ATTR_WS_TRIM, RE_STYLE_ELEMENT, inlineElementsToKeepWhitespaceAround, inlineElementsToKeepWhitespaceWithin, inlineElementsToKeepWhitespace, formControlElements, generalDefaults, tagDefaults, executableScriptsMimetypes, keepScriptsMimetypes, jsonScriptTypes, isSimpleBoolean, isBooleanValue, collapsibleValues, srcsetElements, optionalStartTags, optionalEndTags, headerElements, descriptionElements, pBlockElements, pInlineElements, rubyEndTagOmission, rubyRtcEndTagOmission, optionElements, tableContentElements, tableSectionElements, cellElements, topLevelElements, compactElements, looseElements, trailingElements, htmlElements, reEmptyAttribute, specialContentElements };
98
99
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"AAEA,QAAA,MAAM,WAAW,QAAkB,CAAC;AACpC,QAAA,MAAM,SAAS,QAAkB,CAAC;AAClC,QAAA,MAAM,cAAc,QAAsB,CAAC;AAC3C,QAAA,MAAM,qBAAqB,QAAuB,CAAC;AACnD,QAAA,MAAM,kBAAkB,QAAqB,CAAC;AAC9C,QAAA,MAAM,sBAAsB,QAAqB,CAAC;AAClD,QAAA,MAAM,sBAAsB,QAAc,CAAC;AAC3C,QAAA,MAAM,qBAAqB,QAAkB,CAAC;AAC9C,QAAA,MAAM,yBAAyB,QAA0B,CAAC;AAC1D,QAAA,MAAM,qBAAqB,QAAO,CAAC;AACnC,QAAA,MAAM,aAAa,QAAwB,CAAC;AAC5C,QAAA,MAAM,kBAAkB,QAA+oB,CAAC;AACxqB,QAAA,MAAM,YAAY,QAAO,CAAC;AAC1B,QAAA,MAAM,gBAAgB,QAAgB,CAAC;AACvC,QAAA,MAAM,mBAAmB,QAAkB,CAAC;AAC5C,QAAA,MAAM,eAAe,QAAiC,CAAC;AAKvD,QAAA,MAAM,oCAAoC,aAAqY,CAAC;AAGhb,QAAA,MAAM,oCAAoC,aAAkM,CAAC;AAG7O,QAAA,MAAM,8BAA8B,aAA8C,CAAC;AAGnF,QAAA,MAAM,mBAAmB,aAAoF,CAAC;AAK9G,QAAA,MAAM,eAAe;IACnB,WAAW;IACX,aAAa;IACb,OAAO;IACP,mBAAmB;CACpB,CAAC;AAGF,QAAA,MAAM,WAAW;IACf,IAAI;QAAI,KAAK;;IACb,MAAM;QAAI,IAAI;;IACd,IAAI;QACF,OAAO;QACP,MAAM;;IAER,IAAI;QAAI,GAAG;;IACX,GAAG;QAAI,QAAQ;;IACf,KAAK;QACH,UAAU;QACV,IAAI;;IAEN,IAAI;QAAI,KAAK;;IACb,OAAO;QACL,QAAQ;QACR,SAAS;;IAEX,IAAI;QAAI,KAAK;;IACb,MAAM;QAAI,KAAK;;IACf,KAAK;QAAI,KAAK;;IACd,QAAQ;QAAI,IAAI;;IAChB,KAAK;QAAI,IAAI;;CACd,CAAC;AAMF,QAAA,MAAM,0BAA0B,aAW9B,CAAC;AAEH,QAAA,MAAM,oBAAoB,aAExB,CAAC;AAIH,QAAA,MAAM,eAAe,aAAkgB,CAAC;AAExhB,QAAA,MAAM,cAAc,aAA6B,CAAC;AAMlD,QAAA,MAAM,iBAAiB,0BAGrB,CAAC;AAIH,QAAA,MAAM,cAAc,aAA6B,CAAC;AAIlD,QAAA,MAAM,eAAe,aAUnB,CAAC;AASH,QAAA,MAAM,iBAAiB,aAAyD,CAAC;AAEjF,QAAA,MAAM,eAAe,aAA8K,CAAC;AAEpM,QAAA,MAAM,cAAc,aAAuE,CAAC;AAE5F,QAAA,MAAM,mBAAmB,aAAwB,CAAC;AAElD,QAAA,MAAM,cAAc,aAA4R,CAAC;AAEjT,QAAA,MAAM,eAAe,aAAoE,CAAC;AAE1F,QAAA,MAAM,kBAAkB,aAAqC,CAAC;AAE9D,QAAA,MAAM,qBAAqB,aAAyB,CAAC;AAErD,QAAA,MAAM,cAAc,aAAkC,CAAC;AAEvD,QAAA,MAAM,oBAAoB,aAA8B,CAAC;AAEzD,QAAA,MAAM,oBAAoB,aAAuC,CAAC;AAElE,QAAA,MAAM,YAAY,aAAwB,CAAC;AAE3C,QAAA,MAAM,gBAAgB,aAAoC,CAAC;AAE3D,QAAA,MAAM,eAAe,aAA4B,CAAC;AAElD,QAAA,MAAM,aAAa,aAA2C,CAAC;AAE/D,QAAA,MAAM,gBAAgB,aAA2B,CAAC;AAElD,QAAA,MAAM,YAAY,aAAgwC,CAAC;AAInxC,QAAA,MAAM,gBAAgB,QAE+B,CAAC;AAItD,QAAA,MAAM,sBAAsB,aAA+B,CAAC;AAI5D,OAAO,EAEL,WAAW,EACX,SAAS,EACT,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EAEf,oCAAoC,EACpC,oCAAoC,EACpC,8BAA8B,EAC9B,mBAAmB,EAGnB,eAAe,EACf,WAAW,EAGX,0BAA0B,EAC1B,oBAAoB,EACpB,eAAe,EAGf,eAAe,EACf,cAAc,EACd,iBAAiB,EAGjB,cAAc,EAGd,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,YAAY,EAGZ,gBAAgB,EAChB,sBAAsB,EACvB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"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"}
@@ -23,7 +23,7 @@ declare function canRemovePrecedingTag(optionalEndTag: string, tag: string): boo
23
23
  */
24
24
  declare function canRemoveElement(tag: string, attrs: HTMLAttribute[]): boolean;
25
25
  /**
26
- * @param {string} str - Tag name or HTML-like element spec (e.g., “td” or “<span aria-hidden='true'>”)
26
+ * @param {string} str - Tag name or HTML-like element spec (e.g., `td` or `<span aria-hidden='true'>`)
27
27
  * @param {ProcessedOptions} options - Options object for name normalization
28
28
  * @returns {{tag: string, attrs: Object.<string, string|undefined>|null}|null} Parsed spec or null if invalid
29
29
  */
@@ -176,6 +176,10 @@ declare const optionDefinitions: {
176
176
  description: string;
177
177
  type: string;
178
178
  };
179
+ removeUnusedCSS: {
180
+ description: string;
181
+ type: string;
182
+ };
179
183
  sortAttributes: {
180
184
  description: string;
181
185
  type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"option-definitions.d.ts","sourceRoot":"","sources":["../../../src/lib/option-definitions.js"],"names":[],"mappings":"AAEA,QAAA,MAAM,iBAAiB;IACrB,QAAQ;QACN,WAAW;QACX,IAAI;;IAEN,OAAO;QACL,WAAW;QACX,IAAI;;IAEN,QAAQ;QACN,WAAW;QACX,IAAI;;IAEN,aAAa;QACX,WAAW;QACX,IAAI;;IAEN,2BAA2B;QACzB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,2BAA2B;QACzB,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,sBAAsB;QACtB,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,gBAAgB;QACd,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,6BAA6B;QAC3B,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,wBAAwB;QACtB,WAAW;QACX,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,gBAAgB;QACd,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,aAAa;QACX,WAAW;QACX,IAAI;;IAEN,YAAY;QACV,WAAW;QACX,IAAI;;IAEN,SAAS;QACP,WAAW;QACX,IAAI;;IAEN,QAAQ;QACN,WAAW;QACX,IAAI;;IAEN,SAAS;QACP,WAAW;QACX,IAAI;;IAEN,UAAU;QACR,WAAW;QACX,IAAI;;IAEN,wBAAwB;QACtB,WAAW;QACX,IAAI;;IAEN,aAAa;QACX,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,2BAA2B;QACzB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,mBAAmB;QACjB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,mBAAmB;QACjB,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,mBAAmB;QACjB,WAAW;QACX,IAAI;;IAEN,eAAe;QACb,WAAW;QACX,IAAI;;CAEP,CAAC;AAEF,QAAA,MAAM,cAAc;IAClB,qBAAqB;IACrB,oBAAoB;IAIpB,qBAAqB;IAIrB,wBAAwB;CACzB,CAAC;AAIF,OAAO,EACL,iBAAiB,EACjB,cAAc,EACf,CAAC"}
1
+ {"version":3,"file":"option-definitions.d.ts","sourceRoot":"","sources":["../../../src/lib/option-definitions.js"],"names":[],"mappings":"AAEA,QAAA,MAAM,iBAAiB;IACrB,QAAQ;QACN,WAAW;QACX,IAAI;;IAEN,OAAO;QACL,WAAW;QACX,IAAI;;IAEN,QAAQ;QACN,WAAW;QACX,IAAI;;IAEN,aAAa;QACX,WAAW;QACX,IAAI;;IAEN,2BAA2B;QACzB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,2BAA2B;QACzB,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,sBAAsB;QACtB,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,gBAAgB;QACd,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,6BAA6B;QAC3B,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,wBAAwB;QACtB,WAAW;QACX,IAAI;;IAEN,oBAAoB;QAClB,WAAW;QACX,IAAI;;IAEN,gBAAgB;QACd,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,aAAa;QACX,WAAW;QACX,IAAI;;IAEN,YAAY;QACV,WAAW;QACX,IAAI;;IAEN,SAAS;QACP,WAAW;QACX,IAAI;;IAEN,QAAQ;QACN,WAAW;QACX,IAAI;;IAEN,SAAS;QACP,WAAW;QACX,IAAI;;IAEN,UAAU;QACR,WAAW;QACX,IAAI;;IAEN,wBAAwB;QACtB,WAAW;QACX,IAAI;;IAEN,aAAa;QACX,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,2BAA2B;QACzB,WAAW;QACX,IAAI;;IAEN,qBAAqB;QACnB,WAAW;QACX,IAAI;;IAEN,mBAAmB;QACjB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,kBAAkB;QAChB,WAAW;QACX,IAAI;;IAEN,yBAAyB;QACvB,WAAW;QACX,IAAI;;IAEN,mBAAmB;QACjB,WAAW;QACX,IAAI;;IAEN,eAAe;QACb,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,cAAc;QACZ,WAAW;QACX,IAAI;;IAEN,mBAAmB;QACjB,WAAW;QACX,IAAI;;IAEN,eAAe;QACb,WAAW;QACX,IAAI;;CAEP,CAAC;AAEF,QAAA,MAAM,cAAc;IAClB,qBAAqB;IACrB,oBAAoB;IAIpB,qBAAqB;IAIrB,wBAAwB;CACzB,CAAC;AAIF,OAAO,EACL,iBAAiB,EACjB,cAAc,EACf,CAAC"}
@@ -1,21 +1,47 @@
1
1
  import { LRU } from './utils.js';
2
2
  import type { MinifierOptions, HTMLAttribute } from '../htmlminifier.js';
3
- export type ProcessedOptions = Omit<MinifierOptions, 'preset' | 'canCollapseWhitespace' | 'canTrimWhitespace' | 'ignoreCustomComments' | 'log' | 'minifyCSS' | 'minifyJS' | 'minifyURLs' | 'minifySVG'> & {
3
+ export type CSSContext = {
4
+ usedSymbols?: Set<string>;
5
+ warned: Set<string>;
6
+ };
7
+ export type CSSResult = {
8
+ css: string;
9
+ warnings: string[];
10
+ };
11
+ export type ProcessedOptions = Omit<MinifierOptions, 'preset' | 'canCollapseWhitespace' | 'canTrimWhitespace' | 'ignoreCustomComments' | 'log' | 'minifyCSS' | 'minifyJS' | 'minifyURLs' | 'minifySVG' | 'removeUnusedCSS'> & {
4
12
  name: (name: string) => string;
5
13
  log: (message: any) => unknown;
6
14
  ignoreCustomComments: RegExp[];
7
15
  canCollapseWhitespace: (tag: string, attrs: HTMLAttribute[], defaultFn: (tag: string) => boolean) => boolean;
8
16
  canTrimWhitespace: (tag: string, attrs: HTMLAttribute[], defaultFn: (tag: string) => boolean) => boolean;
9
- minifyCSS: (text: string, type?: string) => string | Promise<string>;
17
+ minifyCSS: (text: string, type?: string, context?: CSSContext) => string | Promise<string>;
10
18
  minifyJS: (text: string, inline?: boolean, isModule?: boolean) => string | Promise<string>;
11
19
  minifyURLs: (text: string) => string | Promise<string>;
12
20
  minifySVG: ((svgContent: string) => string | Promise<string>) | null;
21
+ removeUnusedCSS: {
22
+ safelist: Array<string | RegExp>;
23
+ scripts: boolean;
24
+ } | null;
25
+ cssContext?: CSSContext;
13
26
  nameParent?: (name: string) => string;
14
27
  nameHTML?: (name: string) => string;
15
28
  insideSVG?: boolean;
16
29
  insideForeignContent?: boolean;
17
30
  };
18
31
  /** @import { MinifierOptions, HTMLAttribute } from '../htmlminifier.js' */
32
+ /**
33
+ * Per-document state handed to `minifyCSS`. Its closure hangs off the memoized
34
+ * options object that every `minify()` call with those options shares, so state
35
+ * belonging to one document has to be passed in rather than captured.
36
+ *
37
+ * @typedef {{usedSymbols?: Set<string>, warned: Set<string>}} CSSContext
38
+ */
39
+ /**
40
+ * Minified style sheet plus the warnings its transform produced, cached together
41
+ * so that a cache hit can report what the transform reported
42
+ *
43
+ * @typedef {{css: string, warnings: string[]}} CSSResult
44
+ */
19
45
  /**
20
46
  * Options object produced by `processOptions` and consumed by `minifyHTML` and
21
47
  * the `lib/` helpers; normalization guarantees that the function-valued options
@@ -23,16 +49,18 @@ export type ProcessedOptions = Omit<MinifierOptions, 'preset' | 'canCollapseWhit
23
49
  * minification adds writable internal state on top of the public options
24
50
  * (set on prototype-chain forks during SVG/MathML namespace transitions)
25
51
  *
26
- * @typedef {Omit<MinifierOptions, 'preset' | 'canCollapseWhitespace' | 'canTrimWhitespace' | 'ignoreCustomComments' | 'log' | 'minifyCSS' | 'minifyJS' | 'minifyURLs' | 'minifySVG'> & {
52
+ * @typedef {Omit<MinifierOptions, 'preset' | 'canCollapseWhitespace' | 'canTrimWhitespace' | 'ignoreCustomComments' | 'log' | 'minifyCSS' | 'minifyJS' | 'minifyURLs' | 'minifySVG' | 'removeUnusedCSS'> & {
27
53
  * name: (name: string) => string,
28
54
  * log: (message: any) => unknown,
29
55
  * ignoreCustomComments: RegExp[],
30
56
  * canCollapseWhitespace: (tag: string, attrs: HTMLAttribute[], defaultFn: (tag: string) => boolean) => boolean,
31
57
  * canTrimWhitespace: (tag: string, attrs: HTMLAttribute[], defaultFn: (tag: string) => boolean) => boolean,
32
- * minifyCSS: (text: string, type?: string) => string | Promise<string>,
58
+ * minifyCSS: (text: string, type?: string, context?: CSSContext) => string | Promise<string>,
33
59
  * minifyJS: (text: string, inline?: boolean, isModule?: boolean) => string | Promise<string>,
34
60
  * minifyURLs: (text: string) => string | Promise<string>,
35
61
  * minifySVG: ((svgContent: string) => string | Promise<string>) | null,
62
+ * removeUnusedCSS: {safelist: Array<string | RegExp>, scripts: boolean} | null,
63
+ * cssContext?: CSSContext,
36
64
  * nameParent?: (name: string) => string,
37
65
  * nameHTML?: (name: string) => string,
38
66
  * insideSVG?: boolean,
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/options.js"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAsG,MAAM,YAAY,CAAC;AAOjI,OAAQ,KAAA,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAWrE,YAcG,gBAAgB,GAdT,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,uBAAuB,GAAG,mBAAmB,GAAG,sBAAsB,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAC,GAAG;IACnL,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC;IAC/B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO,CAAC;IAC7G,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO,CAAC;IACzG,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3F,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,SAAS,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACrE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B,CAAkB;AAzBtB,2EAA2E;AAI3E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,wCAAwC;AACxC,iBAAS,qBAAqB,CAAC,OAAO,EAD1B,gBAC0B,WAUrC;AAsCD;;;;GAIG;AACH,QAAA,MAAM,cAAc,iBAJT,eAAe,mGACf;IAAC,eAAe,CAAC,EAAE,WAAW,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,WAAW,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,WAAW,SAAS,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;IAAC,aAAa,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,GAAG,SAAS,CAAA;CAAC,KAC5O,gBA4aZ,CAAC;AAIF,OAAO,EACL,qBAAqB,EACrB,cAAc,EACf,CAAC"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/options.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Collect the class names and IDs a document references.
3
+ *
4
+ * Style sheet contents are excluded, so that a style sheet never counts as
5
+ * evidence for its own selectors. Over-collecting is safe here (a symbol wrongly
6
+ * considered used is merely kept), under-collecting is not.
7
+ *
8
+ * @param {string} html - Raw document markup
9
+ * @param {boolean} includeScripts - Also treat identifiers inside inline `script` elements as used
10
+ * @param {((text: string) => string)} [decode] - Resolves character references in attribute values
11
+ * @param {number} [depth] - Nesting level, counted through `srcdoc`
12
+ * @returns {Set<string>} Symbols to keep
13
+ */
14
+ declare function collectUsedSymbols(html: string, includeScripts: boolean, decode?: ((text: string) => string), depth?: number): Set<string>;
15
+ /**
16
+ * Determine which class/ID symbols a style sheet defines but the document never references.
17
+ * @param {string} css - Style sheet contents
18
+ * @param {Set<string>} used - Symbols the document references
19
+ * @param {Array<string | RegExp>} safelist - Symbols to keep regardless
20
+ * @returns {string[]} Symbols safe to remove
21
+ */
22
+ declare function findUnusedSymbols(css: string, used: Set<string>, safelist: Array<string | RegExp>): string[];
23
+ /**
24
+ * Normalize the `removeUnusedCSS` option into a settled configuration.
25
+ *
26
+ * A misspelled key or a safelist that is not an array would otherwise protect
27
+ * nothing, and that only surfaces as a missing rule much later—so every value
28
+ * that gets dropped is reported.
29
+ *
30
+ * @param {boolean | {safelist?: Array<string | RegExp>, scripts?: boolean} | undefined} option
31
+ * @param {(message: string) => unknown} [warn] - Receives one message per ignored value
32
+ * @returns {{safelist: Array<string | RegExp>, scripts: boolean} | null} Null when disabled
33
+ */
34
+ declare function normalizeUnusedCSSOptions(option: boolean | {
35
+ safelist?: Array<string | RegExp>;
36
+ scripts?: boolean;
37
+ } | undefined, warn?: (message: string) => unknown): {
38
+ safelist: Array<string | RegExp>;
39
+ scripts: boolean;
40
+ } | null;
41
+ export { collectUsedSymbols, findUnusedSymbols, normalizeUnusedCSSOptions };
42
+ //# sourceMappingURL=unused-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unused-css.d.ts","sourceRoot":"","sources":["../../../src/lib/unused-css.js"],"names":[],"mappings":"AA2KA;;;;;;;;;;;;GAYG;AACH,iBAAS,kBAAkB,CAAC,IAAI,EANrB,MAMqB,EAAE,cAAc,EALrC,OAKqC,EAAE,MAAM,AAJrD,CACA,EADQ,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAIoB,EAAE,KAAK,AAH5D,CACA,EADQ,MAGwD,GAFtD,GAAG,CAAC,MAAM,CAAC,CAyGvB;AAED;;;;;;GAMG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EALnB,MAKmB,EAAE,IAAI,EAJzB,GAAG,CAAC,MAAM,CAIe,EAAE,QAAQ,EAHnC,KAAK,CAAC,MAAM,GAAG,MAAM,CAGc,GAFjC,MAAM,EAAE,CAuCpB;AAID;;;;;;;;;;GAUG;AACH,iBAAS,yBAAyB,CAAC,MAAM,EAJ9B,OAAO,GAAG;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAC,GAAG,SAIrC,EAAE,IAAI,AAH5C,CACA,EADQ,CAAC,OAAO,EAAE,MAAM,KAAK,OAGe,GAFlC;IAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,GAAG,IAAI,CAyCvE;AAED,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,EAC1B,CAAC"}
@@ -51,5 +51,13 @@ declare function lowercase(value: string): string;
51
51
  declare function replaceAsync(str: string, regex: RegExp, asyncFn: Function): Promise<string>;
52
52
  /** @param {string | RegExp} value */
53
53
  declare function parseRegExp(value: string | RegExp): RegExp | undefined;
54
- export { stableStringify, LRU, MAX_CACHE_ENTRY_SIZE, hashContent, uniqueId, identity, isThenable, lowercase, replaceAsync, parseRegExp };
54
+ /**
55
+ * Find the index of the `>` that closes an opening tag, correctly skipping
56
+ * over quoted attribute values (which may contain `>`).
57
+ * @param {string} html
58
+ * @param {number} pos - Start position (just after the tag name)
59
+ * @returns {number} Index of the closing `>`, or -1 if not found
60
+ */
61
+ declare function findTagEnd(html: string, pos: number): number;
62
+ export { stableStringify, findTagEnd, LRU, MAX_CACHE_ENTRY_SIZE, hashContent, uniqueId, identity, isThenable, lowercase, replaceAsync, parseRegExp };
55
63
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH,iBAAS,eAAe,CAAC,GAAG,EAHjB,OAGiB,GAFf,MAAM,CAYlB;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;AAID;;;;;;GAMG;AACH,iBAAe,YAAY,CAAC,GAAG,EALpB,MAKoB,EAAE,KAAK,EAJ3B,MAI2B,EAAE,OAAO,UAAA,GAFlC,OAAO,CAAC,MAAM,CAAC,CAc3B;AAID,qCAAqC;AACrC,iBAAS,WAAW,CAAC,KAAK,EADd,MAAM,GAAG,MACK,sBAUzB;AAID,OAAO,EACL,eAAe,EACf,GAAG,EACH,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACZ,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH,iBAAS,eAAe,CAAC,GAAG,EAHjB,OAGiB,GAFf,MAAM,CAYlB;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;AAID;;;;;;GAMG;AACH,iBAAe,YAAY,CAAC,GAAG,EALpB,MAKoB,EAAE,KAAK,EAJ3B,MAI2B,EAAE,OAAO,UAAA,GAFlC,OAAO,CAAC,MAAM,CAAC,CAc3B;AAID,qCAAqC;AACrC,iBAAS,WAAW,CAAC,KAAK,EADd,MAAM,GAAG,MACK,sBAUzB;AAID;;;;;;GAMG;AACH,iBAAS,UAAU,CAAC,IAAI,EAJb,MAIa,EAAE,GAAG,EAHlB,MAGkB,GAFhB,MAAM,CAelB;AAED,OAAO,EACL,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACZ,CAAC"}
@@ -182,7 +182,6 @@
182
182
  "description": "Minify CSS in `style` elements and attributes (uses Lightning CSS)",
183
183
  "type": [
184
184
  "boolean",
185
- "string",
186
185
  "object"
187
186
  ]
188
187
  },
@@ -190,7 +189,6 @@
190
189
  "description": "Minify JavaScript in `script` elements and event attributes (uses Terser or SWC; pass `{\"engine\": \"swc\"}` for SWC)",
191
190
  "type": [
192
191
  "boolean",
193
- "string",
194
192
  "object"
195
193
  ]
196
194
  },
@@ -198,7 +196,6 @@
198
196
  "description": "Minify SVG elements (uses SVGO)",
199
197
  "type": [
200
198
  "boolean",
201
- "string",
202
199
  "object"
203
200
  ]
204
201
  },
@@ -282,6 +279,13 @@
282
279
  "description": "Remove space between attributes whenever possible; note that this will result in invalid HTML",
283
280
  "type": "boolean"
284
281
  },
282
+ "removeUnusedCSS": {
283
+ "description": "Remove rules from `style` elements whose class or ID selectors the document never references (requires `--minify-css`); note that class names only applied by external scripts cannot be detected—use `{\"safelist\": […]}` for those",
284
+ "type": [
285
+ "boolean",
286
+ "object"
287
+ ]
288
+ },
285
289
  "sortAttributes": {
286
290
  "description": "Sort attributes by frequency",
287
291
  "type": "boolean"
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "devDependencies": {
17
17
  "@commitlint/cli": "^21.2.2",
18
18
  "@eslint/js": "^10.0.1",
19
- "@swc/core": "^1.15.47",
19
+ "@swc/core": "^1.16.0",
20
20
  "@types/node": "^26.2.0",
21
21
  "eslint": "^10.8.1",
22
22
  "globals": "^17.11.0",
@@ -95,5 +95,5 @@
95
95
  },
96
96
  "type": "module",
97
97
  "types": "dist/types/htmlminifier.d.ts",
98
- "version": "7.5.3"
98
+ "version": "7.6.0"
99
99
  }
@@ -2,11 +2,13 @@ import { HTMLParser, endTag } from './htmlparser.js';
2
2
  import TokenChain from './tokenchain.js';
3
3
  import { presets, getPreset, getPresetNames } from './presets.js';
4
4
 
5
- import { LRU, identity, isThenable, lowercase, uniqueId } from './lib/utils.js';
5
+ import { LRU, findTagEnd, identity, isThenable, lowercase, uniqueId } from './lib/utils.js';
6
+ import { collectUsedSymbols } from './lib/unused-css.js';
6
7
 
7
8
  import {
8
9
  RE_LEGACY_ENTITIES,
9
10
  RE_ESCAPE_LT,
11
+ RE_STYLE_ELEMENT,
10
12
  inlineElementsToKeepWhitespaceAround,
11
13
  inlineElementsToKeepWhitespaceWithin,
12
14
  specialContentElements,
@@ -437,6 +439,20 @@ import { processOptions } from './lib/options.js';
437
439
  *
438
440
  * Default: `false`
439
441
  *
442
+ * @prop {boolean | {safelist?: Array<string | RegExp>, scripts?: boolean}} [removeUnusedCSS]
443
+ * **Note that this can change how a document renders!**
444
+ *
445
+ * Remove rules from `style` elements whose class or ID selectors the document
446
+ * never references. Requires `minifyCSS` (removal runs through Lightning CSS)
447
+ * and has no effect on `style` or `media` attributes.
448
+ *
449
+ * Class names and IDs are collected from the markup, from `data-*` attributes,
450
+ * and—unless `scripts` is set to `false`—from inline `script` elements. Names
451
+ * that only ever appear in external scripts cannot be detected; list those
452
+ * under `safelist` (strings or regular expressions) to keep them.
453
+ *
454
+ * Default: `false`
455
+ *
440
456
  * @prop {boolean | ((tag: string, attrs: HTMLAttribute[]) => void)} [sortAttributes]
441
457
  * When true, enables sorting of attributes. If a function is provided it
442
458
  * will be used as a custom attribute sorter, which should mutate `attrs`
@@ -570,28 +586,6 @@ const RE_FOREIGN_ELEMENT_PROBE = /<(?:svg|math)[\s/>]/i;
570
586
 
571
587
  // Script merging
572
588
 
573
- /**
574
- * Find the index of the `>` that closes an opening tag, correctly skipping
575
- * over quoted attribute values (which may contain `>`).
576
- * @param {string} html
577
- * @param {number} pos - Start position (just after the tag name)
578
- * @returns {number} Index of the closing `>`, or -1 if not found
579
- */
580
- function findTagEnd(html, pos) {
581
- let i = pos;
582
- while (i < html.length) {
583
- const ch = html[i];
584
- if (ch === '>') return i;
585
- if (ch === '"' || ch === "'") {
586
- const q = ch;
587
- i++;
588
- while (i < html.length && html[i] !== q) i++;
589
- }
590
- i++;
591
- }
592
- return -1;
593
- }
594
-
595
589
  /**
596
590
  * Merge consecutive inline script tags into one (`mergeConsecutiveScripts`).
597
591
  * Only merges scripts that are compatible:
@@ -1092,13 +1086,13 @@ async function minifyHTML(value, options, partialMarkup) {
1092
1086
 
1093
1087
  if (options.minifyCSS !== identity) {
1094
1088
  options.minifyCSS = (function (/** @type {ProcessedOptions['minifyCSS']} */ fn) {
1095
- return function (/** @type {string} */ text, /** @type {string | undefined} */ type) {
1089
+ return function (/** @type {string} */ text, /** @type {string | undefined} */ type, /** @type {ProcessedOptions['cssContext']} */ context) {
1096
1090
  text = text.replace(/** @type {RegExp} */ (uidPattern), function (/** @type {string} */ _match, /** @type {string} */ _prefix, /** @type {string} */ index) {
1097
1091
  const chunks = ignoredCustomMarkupChunks[+index];
1098
1092
  return (chunks?.[1] ?? '') + uidAttr + index + uidAttr + (chunks?.[2] ?? '');
1099
1093
  });
1100
1094
 
1101
- return fn(text, type);
1095
+ return fn(text, type, context);
1102
1096
  };
1103
1097
  })(options.minifyCSS);
1104
1098
  }
@@ -1758,7 +1752,7 @@ async function minifyHTML(value, options, partialMarkup) {
1758
1752
  text = await options.minifyJS(text, false, isModuleScript);
1759
1753
  }
1760
1754
  if (needsMinifyCSS) {
1761
- text = await options.minifyCSS(text);
1755
+ text = await options.minifyCSS(text, undefined, options.cssContext);
1762
1756
  }
1763
1757
  charsFinalize(text);
1764
1758
  })();
@@ -2094,6 +2088,25 @@ export const minify = async function (value, options) {
2094
2088
  }
2095
2089
  // Work on a shallow copy so per-call reassignments don’t reach the cached base
2096
2090
  const processedOptions = /** @type {ProcessedOptions} */ ({ ...processedBase });
2091
+
2092
+ // Warnings are deduplicated per document, so the state has to live on the per-call
2093
+ // copy; the `minifyCSS` closure hangs off the memoized base, shared across calls
2094
+ processedOptions.cssContext = { warned: new Set() };
2095
+
2096
+ // Unused-CSS removal needs the whole document’s symbols before the first `style`
2097
+ // element is minified, so collect them upfront from the raw input. A document
2098
+ // without a style sheet has nothing to remove from, and scanning it would be work
2099
+ // spent on an empty result.
2100
+ if (processedOptions.removeUnusedCSS && RE_STYLE_ELEMENT.test(value)) {
2101
+ processedOptions.cssContext.usedSymbols = collectUsedSymbols(
2102
+ value,
2103
+ processedOptions.removeUnusedCSS.scripts,
2104
+ value.indexOf('&') !== -1
2105
+ ? /** @type {(text: string) => string} */ (await getDecodeHTML())
2106
+ : undefined
2107
+ );
2108
+ }
2109
+
2097
2110
  let result = await minifyHTML(value, processedOptions);
2098
2111
 
2099
2112
  // Post-processing: Merge consecutive inline scripts if enabled