html-minifier-next 4.10.0 → 4.11.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
@@ -139,10 +139,11 @@ Options can be used in config files (camelCase) or via CLI flags (kebab-case wit
139
139
  | Option (config/CLI) | Description | Default |
140
140
  | --- | --- | --- |
141
141
  | `caseSensitive`<br>`--case-sensitive` | Treat attributes in case-sensitive manner (useful for custom HTML elements) | `false` |
142
+ | `collapseAttributeWhitespace`<br>`--collapse-attribute-whitespace` | Trim and collapse whitespace characters within attribute values | `false` |
142
143
  | `collapseBooleanAttributes`<br>`--collapse-boolean-attributes` | [Omit attribute values from boolean attributes](https://perfectionkills.com/experimenting-with-html-minifier#collapse_boolean_attributes) | `false` |
143
144
  | `collapseInlineTagWhitespace`<br>`--collapse-inline-tag-whitespace` | Don’t leave any spaces between `display: inline;` elements when collapsing—use with `collapseWhitespace: true` | `false` |
144
145
  | `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` |
145
- | `conservativeCollapse`<br>`--conservative-collapse` | Always collapse to 1 space (never remove it entirely)—use with `collapseWhitespace: true` | `false` |
146
+ | `conservativeCollapse`<br>`--conservative-collapse` | Always collapse to one space (never remove it entirely)—use with `collapseWhitespace: true` | `false` |
146
147
  | `continueOnMinifyError`<br>`--no-continue-on-minify-error` | Continue on minification errors; when `false`, minification errors throw and abort processing | `true` |
147
148
  | `continueOnParseError`<br>`--continue-on-parse-error` | [Handle parse errors](https://html.spec.whatwg.org/multipage/parsing.html#parse-errors) instead of aborting | `false` |
148
149
  | `customAttrAssign`<br>`--custom-attr-assign` | Arrays of regexes that allow to support custom attribute assign expressions (e.g., `<div flex?="{{mode != cover}}"></div>`) | `[]` |
package/cli.js CHANGED
@@ -117,17 +117,18 @@ const parseValidInt = (optionName) => (value) => {
117
117
 
118
118
  const mainOptions = {
119
119
  caseSensitive: 'Treat attributes in case-sensitive manner (useful for custom HTML elements)',
120
+ collapseAttributeWhitespace: 'Trim and collapse whitespace characters within attribute values',
120
121
  collapseBooleanAttributes: 'Omit attribute values from boolean attributes',
121
- customFragmentQuantifierLimit: ['Set maximum quantifier limit for custom fragments to prevent ReDoS attacks (default: 200)', parseValidInt('customFragmentQuantifierLimit')],
122
122
  collapseInlineTagWhitespace: 'Don’t leave any spaces between “display: inline;” elements when collapsing—use with “--collapse-whitespace”',
123
123
  collapseWhitespace: 'Collapse whitespace that contributes to text nodes in a document tree',
124
- conservativeCollapse: 'Always collapse to 1 space (never remove it entirely)—use with “--collapse-whitespace”',
124
+ conservativeCollapse: 'Always collapse to one space (never remove it entirely)—use with “--collapse-whitespace”',
125
125
  continueOnMinifyError: 'Abort on minification errors',
126
126
  continueOnParseError: 'Handle parse errors instead of aborting',
127
127
  customAttrAssign: ['Arrays of regexes that allow to support custom attribute assign expressions (e.g., “<div flex?="{{mode != cover}}"></div>”)', parseJSONRegExpArray],
128
128
  customAttrCollapse: ['Regex that specifies custom attribute to strip newlines from (e.g., /ng-class/)', parseRegExp],
129
129
  customAttrSurround: ['Arrays of regexes that allow to support custom attribute surround expressions (e.g., “<input {{#if value}}checked="checked"{{/if}}>”)', parseJSONRegExpArray],
130
130
  customEventAttributes: ['Arrays of regexes that allow to support custom event attributes for minifyJS (e.g., “ng-click”)', parseJSONRegExpArray],
131
+ customFragmentQuantifierLimit: ['Set maximum quantifier limit for custom fragments to prevent ReDoS attacks (default: 200)', parseValidInt('customFragmentQuantifierLimit')],
131
132
  decodeEntities: 'Use direct Unicode characters whenever possible',
132
133
  html5: 'Don’t parse input according to the HTML specification (not recommended for modern HTML)',
133
134
  ignoreCustomComments: ['Array of regexes that allow to ignore certain comments, when matched', parseJSONRegExpArray],
@@ -761,6 +761,7 @@ const presets = {
761
761
  useShortDoctype: true
762
762
  },
763
763
  comprehensive: {
764
+ // @@ Add `collapseAttributeWhitespace: true` (also add to preset in demo)
764
765
  caseSensitive: true,
765
766
  collapseBooleanAttributes: true,
766
767
  collapseInlineTagWhitespace: true,
@@ -860,6 +861,14 @@ async function getTerser() {
860
861
  *
861
862
  * Default: `false`
862
863
  *
864
+ * @prop {boolean} [collapseAttributeWhitespace]
865
+ * Collapse multiple whitespace characters within attribute values into a
866
+ * single space. Also trims leading and trailing whitespace from attribute
867
+ * values. Applied as an early normalization step before special attribute
868
+ * handlers (CSS minification, class sorting, etc.) run.
869
+ *
870
+ * Default: `false`
871
+ *
863
872
  * @prop {boolean} [collapseBooleanAttributes]
864
873
  * Collapse boolean attributes to their name only (for example
865
874
  * `disabled="disabled"` → `disabled`).
@@ -1545,6 +1554,12 @@ function isSrcset(attrName, tag) {
1545
1554
  }
1546
1555
 
1547
1556
  async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, minifyHTMLSelf) {
1557
+ // Apply early whitespace normalization if enabled
1558
+ // Preserves special spaces (non-breaking space, hair space, etc.) for consistency with `collapseWhitespace`
1559
+ if (options.collapseAttributeWhitespace) {
1560
+ attrValue = attrValue.replace(/[ \n\r\t\f]+/g, ' ').replace(/^[ \n\r\t\f]+|[ \n\r\t\f]+$/g, '');
1561
+ }
1562
+
1548
1563
  if (isEventAttribute(attrName, options)) {
1549
1564
  attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '');
1550
1565
  return options.minifyJS(attrValue, true);
@@ -5903,6 +5903,7 @@ const presets = {
5903
5903
  useShortDoctype: true
5904
5904
  },
5905
5905
  comprehensive: {
5906
+ // @@ Add `collapseAttributeWhitespace: true` (also add to preset in demo)
5906
5907
  caseSensitive: true,
5907
5908
  collapseBooleanAttributes: true,
5908
5909
  collapseInlineTagWhitespace: true,
@@ -6002,6 +6003,14 @@ async function getTerser() {
6002
6003
  *
6003
6004
  * Default: `false`
6004
6005
  *
6006
+ * @prop {boolean} [collapseAttributeWhitespace]
6007
+ * Collapse multiple whitespace characters within attribute values into a
6008
+ * single space. Also trims leading and trailing whitespace from attribute
6009
+ * values. Applied as an early normalization step before special attribute
6010
+ * handlers (CSS minification, class sorting, etc.) run.
6011
+ *
6012
+ * Default: `false`
6013
+ *
6005
6014
  * @prop {boolean} [collapseBooleanAttributes]
6006
6015
  * Collapse boolean attributes to their name only (for example
6007
6016
  * `disabled="disabled"` → `disabled`).
@@ -6687,6 +6696,12 @@ function isSrcset(attrName, tag) {
6687
6696
  }
6688
6697
 
6689
6698
  async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, minifyHTMLSelf) {
6699
+ // Apply early whitespace normalization if enabled
6700
+ // Preserves special spaces (non-breaking space, hair space, etc.) for consistency with `collapseWhitespace`
6701
+ if (options.collapseAttributeWhitespace) {
6702
+ attrValue = attrValue.replace(/[ \n\r\t\f]+/g, ' ').replace(/^[ \n\r\t\f]+|[ \n\r\t\f]+$/g, '');
6703
+ }
6704
+
6690
6705
  if (isEventAttribute(attrName, options)) {
6691
6706
  attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '');
6692
6707
  return options.minifyJS(attrValue, true);
@@ -44,6 +44,15 @@ export type MinifierOptions = {
44
44
  * Default: `false`
45
45
  */
46
46
  caseSensitive?: boolean;
47
+ /**
48
+ * Collapse multiple whitespace characters within attribute values into a
49
+ * single space. Also trims leading and trailing whitespace from attribute
50
+ * values. Applied as an early normalization step before special attribute
51
+ * handlers (CSS minification, class sorting, etc.) run.
52
+ *
53
+ * Default: `false`
54
+ */
55
+ collapseAttributeWhitespace?: boolean;
47
56
  /**
48
57
  * Collapse boolean attributes to their name only (for example
49
58
  * `disabled="disabled"` → `disabled`).
@@ -1 +1 @@
1
- {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAovEO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;;;;UA3tES,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;;;;;;;;;;oBAMP,OAAO;;;;;;;;yBASP,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;;;;;;;;;;;;;;;;;;;;;;;;;;gCAOP,MAAM,EAAE;;;;;;;;yBAyBR,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;;wBAnYkC,cAAc;0BAAd,cAAc;+BAAd,cAAc"}
1
+ {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/presets.js"],"names":[],"mappings":"AAgDA;;;;GAIG;AACH,gCAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CAMvB;AAED;;;GAGG;AACH,kCAFa,MAAM,EAAE,CAIpB"}
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/presets.js"],"names":[],"mappings":"AAiDA;;;;GAIG;AACH,gCAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CAMvB;AAED;;;GAGG;AACH,kCAFa,MAAM,EAAE,CAIpB"}
package/package.json CHANGED
@@ -84,5 +84,5 @@
84
84
  "test:watch": "node --test --watch tests/*.spec.js"
85
85
  },
86
86
  "type": "module",
87
- "version": "4.10.0"
87
+ "version": "4.11.0"
88
88
  }
@@ -61,6 +61,14 @@ async function getTerser() {
61
61
  *
62
62
  * Default: `false`
63
63
  *
64
+ * @prop {boolean} [collapseAttributeWhitespace]
65
+ * Collapse multiple whitespace characters within attribute values into a
66
+ * single space. Also trims leading and trailing whitespace from attribute
67
+ * values. Applied as an early normalization step before special attribute
68
+ * handlers (CSS minification, class sorting, etc.) run.
69
+ *
70
+ * Default: `false`
71
+ *
64
72
  * @prop {boolean} [collapseBooleanAttributes]
65
73
  * Collapse boolean attributes to their name only (for example
66
74
  * `disabled="disabled"` → `disabled`).
@@ -746,6 +754,12 @@ function isSrcset(attrName, tag) {
746
754
  }
747
755
 
748
756
  async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, minifyHTMLSelf) {
757
+ // Apply early whitespace normalization if enabled
758
+ // Preserves special spaces (non-breaking space, hair space, etc.) for consistency with `collapseWhitespace`
759
+ if (options.collapseAttributeWhitespace) {
760
+ attrValue = attrValue.replace(/[ \n\r\t\f]+/g, ' ').replace(/^[ \n\r\t\f]+|[ \n\r\t\f]+$/g, '');
761
+ }
762
+
749
763
  if (isEventAttribute(attrName, options)) {
750
764
  attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '');
751
765
  return options.minifyJS(attrValue, true);
package/src/presets.js CHANGED
@@ -22,6 +22,7 @@ export const presets = {
22
22
  useShortDoctype: true
23
23
  },
24
24
  comprehensive: {
25
+ // @@ Add `collapseAttributeWhitespace: true` (also add to preset in demo)
25
26
  caseSensitive: true,
26
27
  collapseBooleanAttributes: true,
27
28
  collapseInlineTagWhitespace: true,