html-minifier-next 8.5.1 → 8.5.2

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
@@ -156,13 +156,13 @@ Options can be used in config files (camelCase) or via CLI flags (kebab-case wit
156
156
  | `inlineCustomElements`<br>`--inline-custom-elements` | Array of names of custom elements which are inline, for whitespace handling—use with `collapseWhitespace` | `[]` |
157
157
  | `keepClosingSlash`<br>`--keep-closing-slash` | Keep the trailing slash on void elements and other start tags that carry one, and read it as closing the element | `false` |
158
158
  | `maxInputLength`<br>`--max-input-length` | Maximum input length to prevent ReDoS attacks (disabled by default) | `undefined` |
159
- | `maxLineLength`<br>`--max-line-length` | Specify a maximum line length; compressed output will be split by newlines at valid HTML split-points | `undefined` |
159
+ | `maxLineLength`<br>`--max-line-length` | Specify a maximum line length; output will be split by newlines in tags only (between attributes or before a tag’s `>`), where they can’t change the page, so lines may run longer | `undefined` |
160
160
  | `mergeScripts`<br>`--merge-scripts` | Merge consecutive inline `script` elements into one (only merges compatible scripts with same `type`, matching `async`/`defer`/`nomodule`/`nonce`) | `false` |
161
161
  | `minifyCSS`<br>`--minify-css` | Minify CSS in `style` elements and attributes (uses [Lightning CSS](https://lightningcss.dev/)) | `false` (could be `true`, `Object`, `Function(text, type)`) |
162
162
  | `minifyJS`<br>`--minify-js` | Minify JavaScript in `script` elements and event attributes (uses [Terser](https://terser.org/) or [SWC](https://swc.rs/)) | `false` (could be `true`, `Object`, `Function(text, inline)`) |
163
163
  | `minifySVG`<br>`--minify-svg` | Minify SVG elements (uses [SVGO](https://svgo.dev/)) | `false` (could be `true`, `Object`) |
164
164
  | `minifyURLs`<br>`--minify-urls` | Minify URLs in various attributes | `false` (could be `true`, `String`, `Object`, `Function(text)`) |
165
- | `noNewlinesBeforeTagClose`<br>`--no-newlines-before-tag-close` | Never add a newline before a tag that closes an element—use with `maxLineLength` | `false` |
165
+ | `noNewlinesBeforeTagClose`<br>`--no-newlines-before-tag-close` | Never split a line in a tag that closes an element—use with `maxLineLength` | `false` |
166
166
  | `partialMarkup`<br>`--partial-markup` | Treat input as a partial HTML fragment, preserving stray end tags (closing tags without opening tags) and preventing auto-closing of unclosed tags at end of input | `false` |
167
167
  | `preserveLineBreaks`<br>`--preserve-line-breaks` | Always collapse to one line break (never remove it entirely) when whitespace between tags includes a line break—use with [`collapseWhitespace`](#combining-whitespace-options) | `false` |
168
168
  | `preventAttributesEscaping`<br>`--prevent-attributes-escaping` | Prevents the escaping of the values of attributes | `false` |
@@ -244,7 +244,8 @@ export type MinifierOptions = {
244
244
  maxInputLength?: number;
245
245
  /**
246
246
  * Maximum line length for the output. When set the minifier will wrap
247
- * output to the given number of characters where possible.
247
+ * output to the given number of characters where possible, splitting
248
+ * lines only in tags—between attributes or before a tag’s `>`.
248
249
  *
249
250
  * Default: No limit
250
251
  */
@@ -308,8 +309,8 @@ export type MinifierOptions = {
308
309
  */
309
310
  minifySVG?: boolean | Object;
310
311
  /**
311
- * When wrapping lines, prevent inserting a newline directly before a
312
- * closing tag (useful to keep tags like `</a>` on the same line).
312
+ * When wrapping lines, never split a line in an end tag (e.g., keeps
313
+ * `</a>` from becoming `</a` and `>` on two lines).
313
314
  *
314
315
  * Default: `false`
315
316
  */
@@ -1 +1 @@
1
- {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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"}
@@ -11,7 +11,6 @@ export type HTMLParserHandler = {
11
11
  customAttrSurround?: RegExp[][] | undefined;
12
12
  customAttrAssign?: RegExp[] | undefined;
13
13
  };
14
- export declare const endTag: RegExp;
15
14
  export declare class HTMLParser {
16
15
  html: string;
17
16
  handler: HTMLParserHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AAeG,YAYG,iBAAiB,GAZV;IACR,KAAK,CAAC,WAAW;IACjB,GAAG,CAAC,WAAW;IACf,KAAK,CAAC,WAAW;IACjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,WAAW;IACnB,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CACxC,CAAmB;AA0CvB,eAAO,MAAM,MAAM,QAA8C,CAAC;AAoLlE,qBAAa,UAAU;IAMd,IAAI;IACJ,OAAO;IANd;;;OAGG;IACH,YAAY,IAAI,EAHL,MAGK,EAAE,OAAO,EAFd,iBAEc,EAGxB;IAEK,KAAK,kBA2yBV;CACF"}
1
+ {"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AAeG,YAYG,iBAAiB,GAZV;IACR,KAAK,CAAC,WAAW;IACjB,GAAG,CAAC,WAAW;IACf,KAAK,CAAC,WAAW;IACjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,WAAW;IACnB,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CACxC,CAAmB;AA6NvB,qBAAa,UAAU;IAMd,IAAI;IACJ,OAAO;IANd;;;OAGG;IACH,YAAY,IAAI,EAHL,MAGK,EAAE,OAAO,EAFd,iBAEc,EAGxB;IAEK,KAAK,kBA2yBV;CACF"}
@@ -165,7 +165,7 @@
165
165
  "minimum": 0
166
166
  },
167
167
  "maxLineLength": {
168
- "description": "Specify a maximum line length; compressed output will be split by newlines at valid HTML split-points",
168
+ "description": "Specify a maximum line length; output will be split by newlines in tags only (between attributes or before a tag’s `>`), where they can’t change the page, so lines may run longer",
169
169
  "type": "integer",
170
170
  "minimum": 0
171
171
  },
@@ -203,7 +203,7 @@
203
203
  ]
204
204
  },
205
205
  "noNewlinesBeforeTagClose": {
206
- "description": "Never add a newline before a tag that closes an element—use with `--max-line-length`",
206
+ "description": "Never split a line in a tag that closes an element—use with `--max-line-length`",
207
207
  "type": "boolean"
208
208
  },
209
209
  "partialMarkup": {
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "@commitlint/cli": "^21.2.2",
18
18
  "@eslint/js": "^10.0.1",
19
19
  "@swc/core": "^1.16.2",
20
- "@types/node": "^26.5.1",
20
+ "@types/node": "^26.6.1",
21
21
  "eslint": "^10.10.0",
22
22
  "globals": "^17.12.0",
23
23
  "typescript": "^7.0.2",
@@ -95,5 +95,5 @@
95
95
  },
96
96
  "type": "module",
97
97
  "types": "dist/types/htmlminifier.d.ts",
98
- "version": "8.5.1"
98
+ "version": "8.5.2"
99
99
  }
@@ -1,4 +1,4 @@
1
- import { HTMLParser, endTag } from './htmlparser.js';
1
+ import { HTMLParser } from './htmlparser.js';
2
2
  import TokenChain from './tokenchain.js';
3
3
  import { presets, getPreset, getPresetNames } from './presets.js';
4
4
 
@@ -297,7 +297,8 @@ import { toFragment, replaceCustomFragments } from './lib/fragments.js';
297
297
  *
298
298
  * @prop {number} [maxLineLength]
299
299
  * Maximum line length for the output. When set the minifier will wrap
300
- * output to the given number of characters where possible.
300
+ * output to the given number of characters where possible, splitting
301
+ * lines only in tags—between attributes or before a tag’s `>`.
301
302
  *
302
303
  * Default: No limit
303
304
  *
@@ -350,8 +351,8 @@ import { toFragment, replaceCustomFragments } from './lib/fragments.js';
350
351
  * Default: `false`
351
352
  *
352
353
  * @prop {boolean} [noNewlinesBeforeTagClose]
353
- * When wrapping lines, prevent inserting a newline directly before a
354
- * closing tag (useful to keep tags like `</a>` on the same line).
354
+ * When wrapping lines, never split a line in an end tag (e.g., keeps
355
+ * `</a>` from becoming `</a` and `>` on two lines).
355
356
  *
356
357
  * Default: `false`
357
358
  *
@@ -1047,6 +1048,8 @@ async function minifyHTML(value, options, partialMarkup) {
1047
1048
 
1048
1049
  /** @type {string[]} */
1049
1050
  const buffer = [];
1051
+ // Parallel to `buffer`: whether an entry belongs to a start or end tag, the only place lines may break
1052
+ const bufferTags = options.maxLineLength ? /** @type {boolean[]} */ ([]) : null;
1050
1053
  /** @type {string} */
1051
1054
  let charsPrevTag = '';
1052
1055
  let currentChars = '';
@@ -1278,12 +1281,22 @@ async function minifyHTML(value, options, partialMarkup) {
1278
1281
  return options.canTrimWhitespace(tag, attrs, defaultCanTrimWhitespace);
1279
1282
  }
1280
1283
 
1284
+ function bufferPush(/** @type {string} */ entry, /** @type {boolean} */ isTag) {
1285
+ buffer.push(entry);
1286
+ bufferTags?.push(isTag);
1287
+ }
1288
+
1289
+ function bufferTruncate(/** @type {number} */ length) {
1290
+ buffer.length = Math.max(0, length);
1291
+ if (bufferTags) bufferTags.length = buffer.length;
1292
+ }
1293
+
1281
1294
  function removeStartTag() {
1282
1295
  let index = buffer.length - 1;
1283
1296
  while (index > 0 && !RE_START_TAG.test(buffer[index] ?? '')) {
1284
1297
  index--;
1285
1298
  }
1286
- buffer.length = Math.max(0, index);
1299
+ bufferTruncate(index);
1287
1300
  }
1288
1301
 
1289
1302
  // Whether the element being parsed holds text rather than markup. The namespace decides
@@ -1339,13 +1352,14 @@ async function minifyHTML(value, options, partialMarkup) {
1339
1352
  const noTrim = stackNoTrimWhitespace.length > 0;
1340
1353
  if (index < buffer.length - 1 && (keepsWhitespace() || noTrim) && RE_END_TAG.test(buffer[index] ?? '')) {
1341
1354
  buffer.splice(index, 1);
1355
+ bufferTags?.splice(index, 1);
1342
1356
  // Only collapsed whitespace can merge
1343
1357
  if (options.collapseWhitespace && !noTrim) {
1344
1358
  mergeWhitespaceRuns(index);
1345
1359
  }
1346
1360
  return;
1347
1361
  }
1348
- buffer.length = Math.max(0, index);
1362
+ bufferTruncate(index);
1349
1363
  }
1350
1364
 
1351
1365
  // Look for trailing whitespaces, bypass any inline tags
@@ -1545,7 +1559,7 @@ async function minifyHTML(value, options, partialMarkup) {
1545
1559
  if (text) {
1546
1560
  hasChars = true;
1547
1561
  }
1548
- buffer.push(text);
1562
+ bufferPush(text, false);
1549
1563
  }
1550
1564
 
1551
1565
  // Comment finalization (sync): Optional tag handling, `htmlmin:ignore` whitespace collapsing, buffer push
@@ -1656,7 +1670,7 @@ async function minifyHTML(value, options, partialMarkup) {
1656
1670
  }
1657
1671
  }
1658
1672
 
1659
- buffer.push(comment);
1673
+ bufferPush(comment, false);
1660
1674
  }
1661
1675
 
1662
1676
  // Inline scripts are minified one at a time as the parse reaches them, which serializes
@@ -1839,7 +1853,7 @@ async function minifyHTML(value, options, partialMarkup) {
1839
1853
  const needsXMLSlash = unary && Boolean(options.insideSVG) && Boolean(options.minifySVG);
1840
1854
  const hasUnarySlash = needsXMLSlash || (unarySlash && (useNameParentForTag ? optionsParent : options).keepClosingSlash);
1841
1855
 
1842
- buffer.push(openTag);
1856
+ bufferPush(openTag, true);
1843
1857
 
1844
1858
  const fragmentJoinsTag = uidAttrExactPattern ? joinFragmentAttrs(attrs) : false;
1845
1859
  // Whatever runs into the tag name has to stay first
@@ -1883,7 +1897,7 @@ async function minifyHTML(value, options, partialMarkup) {
1883
1897
  }
1884
1898
  if (lastKeptIndex !== -1) {
1885
1899
  if (!fragmentJoinsTag) {
1886
- buffer.push(' ');
1900
+ bufferPush(' ', true);
1887
1901
  }
1888
1902
  for (let i = 0; i <= lastKeptIndex; i++) {
1889
1903
  const normalizedAttr = normalizedAttrs[i];
@@ -1893,7 +1907,11 @@ async function minifyHTML(value, options, partialMarkup) {
1893
1907
  }
1894
1908
  const builtAttr = buildAttr(normalizedAttr, hasUnarySlash, options, i === lastKeptIndex, uidAttr);
1895
1909
  // One entry with the tag name, so that no line break can come between them
1896
- buffer.push(i === 0 && fragmentJoinsTag ? buffer.pop() + builtAttr : builtAttr);
1910
+ if (i === 0 && fragmentJoinsTag) {
1911
+ buffer[buffer.length - 1] += builtAttr;
1912
+ } else {
1913
+ bufferPush(builtAttr, true);
1914
+ }
1897
1915
  }
1898
1916
  }
1899
1917
  } else if (optional && optionalStartTags.has(tag)) {
@@ -1901,7 +1919,7 @@ async function minifyHTML(value, options, partialMarkup) {
1901
1919
  optionalStartTag = tag;
1902
1920
  }
1903
1921
 
1904
- buffer.push(buffer.pop() + (hasUnarySlash ? '/' : '') + '>');
1922
+ buffer[buffer.length - 1] += (hasUnarySlash ? '/' : '') + '>';
1905
1923
 
1906
1924
  if (autoGenerated && !options.includeAutoGeneratedTags) {
1907
1925
  removeStartTag();
@@ -2010,7 +2028,7 @@ async function minifyHTML(value, options, partialMarkup) {
2010
2028
  if (autoGenerated && !options.includeAutoGeneratedTags) {
2011
2029
  optionalEndTagEmitted = false;
2012
2030
  } else {
2013
- buffer.push(endTagText);
2031
+ bufferPush(endTagText, true);
2014
2032
  }
2015
2033
  charsPrevTag = '/' + tag;
2016
2034
  if (!inlineElements.has(tag)) {
@@ -2023,7 +2041,7 @@ async function minifyHTML(value, options, partialMarkup) {
2023
2041
  if (autoGenerated && !options.includeAutoGeneratedTags) {
2024
2042
  optionalEndTagEmitted = false;
2025
2043
  } else {
2026
- buffer.push(endTagText);
2044
+ bufferPush(endTagText, true);
2027
2045
  }
2028
2046
  charsPrevTag = '/' + tag;
2029
2047
  if (!inlineElements.has(tag)) {
@@ -2099,10 +2117,10 @@ async function minifyHTML(value, options, partialMarkup) {
2099
2117
  commentFinalize(text);
2100
2118
  },
2101
2119
  doctype: function (/** @type {string} */ doctype) {
2102
- buffer.push(options.useShortDoctype
2120
+ bufferPush(options.useShortDoctype
2103
2121
  ? '<!doctype' +
2104
2122
  (options.removeTagWhitespace ? '' : ' ') + 'html>'
2105
- : collapseWhitespaceAll(doctype));
2123
+ : collapseWhitespaceAll(doctype), false);
2106
2124
  }
2107
2125
  });
2108
2126
 
@@ -2119,7 +2137,10 @@ async function minifyHTML(value, options, partialMarkup) {
2119
2137
  );
2120
2138
  for (let i = svgBlocks.length - 1; i >= 0; i--) {
2121
2139
  const block = svgBlocks[i];
2122
- if (block) buffer.splice(block.start, block.end - block.start, optimized[i] ?? '');
2140
+ if (block) {
2141
+ buffer.splice(block.start, block.end - block.start, optimized[i] ?? '');
2142
+ bufferTags?.splice(block.start, block.end - block.start, false);
2143
+ }
2123
2144
  }
2124
2145
  }
2125
2146
 
@@ -2138,7 +2159,7 @@ async function minifyHTML(value, options, partialMarkup) {
2138
2159
  squashTrailingWhitespace('br');
2139
2160
  }
2140
2161
 
2141
- return joinResultSegments(buffer, options, uidPattern
2162
+ return joinResultSegments(buffer, bufferTags ?? [], [uidAttr, uidIgnore].filter(marker => marker !== undefined), options, uidPattern
2142
2163
  ? function (/** @type {string} */ str) {
2143
2164
  return str.replace(/** @type {RegExp} */ (uidPattern), function (/** @type {string} */ match, /** @type {string} */ prefix, /** @type {string} */ index, /** @type {string} */ suffix, /** @type {number} */ offset, /** @type {string} */ string) {
2144
2165
  const chunks = ignoredCustomMarkupChunks[+index];
@@ -2173,46 +2194,74 @@ async function minifyHTML(value, options, partialMarkup) {
2173
2194
 
2174
2195
  /**
2175
2196
  * @param {string[]} results
2197
+ * @param {boolean[]} resultTags Whether each result belongs to a start or end tag
2198
+ * @param {string[]} markers Custom fragment and `htmlmin:ignore` placeholder markers
2176
2199
  * @param {ProcessedOptions} options
2177
2200
  * @param {Function} restoreCustom
2178
2201
  * @param {Function} restoreIgnore
2179
2202
  */
2180
- function joinResultSegments(results, options, restoreCustom, restoreIgnore) {
2203
+ function joinResultSegments(results, resultTags, markers, options, restoreCustom, restoreIgnore) {
2181
2204
  let str;
2182
2205
  const maxLineLength = options.maxLineLength;
2183
- const noNewlinesBeforeTagClose = options.noNewlinesBeforeTagClose;
2184
2206
 
2185
2207
  if (maxLineLength) {
2186
- let line = ''; const lines = [];
2187
- // Index-based scan—`Array.shift()` is O(n) per call, which would make this
2188
- // loop quadratic on documents with many segments
2189
- let index = 0;
2190
- while (index < results.length) {
2191
- const len = line.length;
2192
- const cur = results[index] ?? '';
2193
- const end = cur.indexOf('\n');
2194
- const isClosingTag = Boolean(cur.match(endTag));
2195
- const shouldKeepSameLine = noNewlinesBeforeTagClose && isClosingTag;
2196
-
2197
- if (end < 0) {
2198
- line += restoreIgnore(restoreCustom(cur));
2199
- index++;
2200
- } else {
2201
- line += restoreIgnore(restoreCustom(cur.slice(0, end)));
2202
- results[index] = cur.slice(end + 1);
2208
+ // Whitespace in tags is the only whitespace that can’t change the output, so lines break
2209
+ // there alone—in place of the space between attributes, or right before a tag’s `>`
2210
+ const noNewlinesBeforeTagClose = options.noNewlinesBeforeTagClose;
2211
+ /** @type {string[]} */
2212
+ const lines = [];
2213
+ let lineLength = 0;
2214
+ // Output since the last break opportunity, and what that opportunity is when not taken;
2215
+ // fragments are restored by chunk, as whitespace around them decides how they come back
2216
+ let chunk = '';
2217
+ /** @type {string | null} */
2218
+ let separator = null;
2219
+ const flush = (/** @type {string | null} */ nextSeparator) => {
2220
+ chunk = restoreIgnore(restoreCustom(chunk));
2221
+ const newline = chunk.indexOf('\n');
2222
+ const head = newline < 0 ? chunk.length : newline;
2223
+ // A line already too long gains nothing from moving a `>` that ends a line of its own
2224
+ const isUseless = separator === '' && head === 1 && lineLength > maxLineLength;
2225
+ if (separator !== null) {
2226
+ if (lineLength > 0 && lineLength + separator.length + head > maxLineLength && !isUseless) {
2227
+ lines.push('\n');
2228
+ lineLength = 0;
2229
+ } else if (separator) {
2230
+ lines.push(separator);
2231
+ lineLength += separator.length;
2232
+ }
2203
2233
  }
2204
- if (len > 0 && line.length > maxLineLength && !shouldKeepSameLine) {
2205
- lines.push(line.slice(0, len));
2206
- line = line.slice(len);
2207
- } else if (end >= 0) {
2208
- lines.push(line);
2209
- line = '';
2234
+ lines.push(chunk);
2235
+ lineLength = newline < 0 ? lineLength + chunk.length : chunk.length - chunk.lastIndexOf('\n') - 1;
2236
+ chunk = '';
2237
+ separator = nextSeparator;
2238
+ };
2239
+ for (let index = 0; index < results.length; index++) {
2240
+ const result = results[index] ?? '';
2241
+ if (!resultTags[index]) {
2242
+ chunk += result;
2243
+ } else if (markers.length && markers.some(marker => result.includes(marker))) {
2244
+ // Whitespace next to a fragment stays as is, as it may belong to it
2245
+ if (!chunk && separator !== null) {
2246
+ chunk = separator;
2247
+ separator = null;
2248
+ }
2249
+ chunk += result;
2250
+ } else if (result.charCodeAt(result.length - 1) === 32 /* space */) {
2251
+ chunk += result.slice(0, -1);
2252
+ flush(' ');
2253
+ } else if (result.charCodeAt(result.length - 1) === 62 /* > */ &&
2254
+ result.charCodeAt(result.length - 2) !== 47 /* / */ &&
2255
+ !(noNewlinesBeforeTagClose && result.startsWith('</'))) {
2256
+ chunk += result.slice(0, -1);
2257
+ flush('');
2258
+ chunk = '>';
2259
+ } else {
2260
+ chunk += result;
2210
2261
  }
2211
2262
  }
2212
- if (line) {
2213
- lines.push(line);
2214
- }
2215
- str = lines.join('\n');
2263
+ flush(null);
2264
+ str = lines.join('');
2216
2265
  } else {
2217
2266
  str = restoreIgnore(restoreCustom(results.join('')));
2218
2267
  }
package/src/htmlparser.js CHANGED
@@ -67,7 +67,6 @@ const qnameCapture = (function () {
67
67
  })();
68
68
  const startTagOpen = new RegExp('^<' + qnameCapture);
69
69
  const endTagOpen = new RegExp('^</' + qnameCapture);
70
- export const endTag = new RegExp('^</' + qnameCapture + '[^>]*>');
71
70
 
72
71
  let IS_REGEX_CAPTURING_BROKEN = false;
73
72
  'x'.replace(/x(.)?/g, function (/** @type {string} */ m, /** @type {string | undefined} */ g) {
@@ -101,7 +101,7 @@ const optionDefinitions = {
101
101
  type: 'int'
102
102
  },
103
103
  maxLineLength: {
104
- description: 'Specify a maximum line length; compressed output will be split by newlines at valid HTML split-points',
104
+ description: 'Specify a maximum line length; output will be split by newlines in tags only (between attributes or before a tag’s `>`), where they can’t change the page, so lines may run longer',
105
105
  type: 'int'
106
106
  },
107
107
  mergeScripts: {
@@ -125,7 +125,7 @@ const optionDefinitions = {
125
125
  type: 'json'
126
126
  },
127
127
  noNewlinesBeforeTagClose: {
128
- description: 'Never add a newline before a tag that closes an element—use with `--max-line-length`',
128
+ description: 'Never split a line in a tag that closes an element—use with `--max-line-length`',
129
129
  type: 'boolean'
130
130
  },
131
131
  partialMarkup: {