html-minifier-next 8.5.1 → 8.5.3

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"}
@@ -26,7 +26,10 @@ declare const RE_EMPTY_ATTRIBUTE: RegExp;
26
26
  declare const inlineElementsToKeepWhitespaceAround: Set<string>;
27
27
  declare const inlineElementsToKeepWhitespaceWithin: Set<string>;
28
28
  declare const inlineElementsToKeepWhitespace: Set<string>;
29
- declare const formControlElements: Set<string>;
29
+ /** @param {Iterable<string>} names */
30
+ declare const toEndTags: (names: Iterable<string>) => Set<string>;
31
+ declare const inlineElementsToKeepWhitespaceWithinEither: Set<string>;
32
+ declare const formControlElementsEither: Set<string>;
30
33
  declare const generalDefaults: {
31
34
  autocorrect: string;
32
35
  fetchpriority: string;
@@ -124,5 +127,5 @@ declare const svgoPluginsInline: {
124
127
  };
125
128
  }[];
126
129
  declare const namesForeignMixedCase: Map<string, string>;
127
- export { RE_WS_START, RE_WS_END, RE_WS_ONLY, RE_WS_NBSP_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_ESCAPE_LT_RAW_TEXT, RE_HTML_ENCODING, RE_ATTR_WS_CHECK, RE_ATTR_WS_COLLAPSE, RE_ATTR_WS_TRIM, RE_STYLE_ELEMENT, RE_EMPTY_ATTRIBUTE, inlineElementsToKeepWhitespaceAround, inlineElementsToKeepWhitespaceWithin, inlineElementsToKeepWhitespace, formControlElements, generalDefaults, tagDefaults, executableScriptsMimetypes, keepScriptsMimetypes, jsonScriptTypes, isSimpleBoolean, isBooleanValue, collapsibleValues, srcsetElements, MISSING_DEPENDENCY, namesForeignMixedCase, svgoPluginsInline, optionalStartTags, optionalEndTags, headerElements, descriptionElements, pBlockElements, pInlineElements, rubyEndTagOmission, rubyRtcEndTagOmission, optionElements, tableContentElements, tableSectionElements, cellElements, topLevelElements, compactElements, looseElements, trailingElements, htmlElements, specialContentElements, genericRawTextElements, endlessRawTextElements, escapableRawTextElements, rawTextElements };
130
+ export { RE_WS_START, RE_WS_END, RE_WS_ONLY, RE_WS_NBSP_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_ESCAPE_LT_RAW_TEXT, RE_HTML_ENCODING, RE_ATTR_WS_CHECK, RE_ATTR_WS_COLLAPSE, RE_ATTR_WS_TRIM, RE_STYLE_ELEMENT, RE_EMPTY_ATTRIBUTE, inlineElementsToKeepWhitespaceAround, inlineElementsToKeepWhitespaceWithin, inlineElementsToKeepWhitespace, inlineElementsToKeepWhitespaceWithinEither, formControlElementsEither, toEndTags, generalDefaults, tagDefaults, executableScriptsMimetypes, keepScriptsMimetypes, jsonScriptTypes, isSimpleBoolean, isBooleanValue, collapsibleValues, srcsetElements, MISSING_DEPENDENCY, namesForeignMixedCase, svgoPluginsInline, optionalStartTags, optionalEndTags, headerElements, descriptionElements, pBlockElements, pInlineElements, rubyEndTagOmission, rubyRtcEndTagOmission, optionElements, tableContentElements, tableSectionElements, cellElements, topLevelElements, compactElements, looseElements, trailingElements, htmlElements, specialContentElements, genericRawTextElements, endlessRawTextElements, escapableRawTextElements, rawTextElements };
128
131
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@
4
4
  /** @param {string} str */
5
5
  declare const trimWhitespace: (str: string) => string;
6
6
  /** @param {string} str */
7
+ declare function endsWithWhitespace(str: string): boolean;
8
+ /** @param {string} str */
7
9
  declare function collapseWhitespaceAll(str: string): string;
8
10
  /**
9
11
  * @param {string} str
@@ -16,6 +18,45 @@ declare function collapseWhitespace(str: string, options: {
16
18
  preserveLineBreaks?: boolean | undefined;
17
19
  conservativeCollapse?: boolean | undefined;
18
20
  }, trimLeft: boolean, trimRight: boolean, collapseAll?: boolean): string;
21
+ export type InlineSets = {
22
+ /**
23
+ * - Elements whose surrounding whitespace is kept
24
+ */
25
+ around: Set<string>;
26
+ /**
27
+ * - The same, spelled as end tags
28
+ */
29
+ aroundEnd: Set<string>;
30
+ /**
31
+ * - Elements whose inner whitespace is kept
32
+ */
33
+ within: Set<string>;
34
+ /**
35
+ * - The same, spelled as end tags
36
+ */
37
+ withinEnd: Set<string>;
38
+ /**
39
+ * - `within` under both spellings
40
+ */
41
+ withinEither: Set<string>;
42
+ };
43
+ /**
44
+ * @typedef {object} InlineSets
45
+ * @prop {Set<string>} around - Elements whose surrounding whitespace is kept
46
+ * @prop {Set<string>} aroundEnd - The same, spelled as end tags
47
+ * @prop {Set<string>} within - Elements whose inner whitespace is kept
48
+ * @prop {Set<string>} withinEnd - The same, spelled as end tags
49
+ * @prop {Set<string>} withinEither - `within` under both spellings
50
+ */
51
+ /**
52
+ * Inline-element membership for the whitespace pass, each set paired with its end-tag
53
+ * spelling so a lookup takes the tag as it comes rather than slicing off the slash
54
+ * @param {Set<string>} around
55
+ * @param {Set<string>} within
56
+ * @returns {InlineSets}
57
+ */
58
+ declare function buildInlineSets(around: Set<string>, within: Set<string>): InlineSets;
59
+ declare const defaultInlineSets: InlineSets;
19
60
  /**
20
61
  * @param {string} str
21
62
  * @param {string} prevTag
@@ -23,8 +64,7 @@ declare function collapseWhitespace(str: string, options: {
23
64
  * @param {Array<{name: string, value?: string}>} prevAttrs
24
65
  * @param {Array<{name: string, value?: string}>} nextAttrs
25
66
  * @param {{preserveLineBreaks?: boolean, conservativeCollapse?: boolean, collapseInlineTagWhitespace?: boolean}} options
26
- * @param {Set<string>} inlineElements
27
- * @param {Set<string>} inlineTextSet
67
+ * @param {InlineSets} inlineSets
28
68
  */
29
69
  declare function collapseWhitespaceSmart(str: string, prevTag: string, nextTag: string, prevAttrs: Array<{
30
70
  name: string;
@@ -36,10 +76,10 @@ declare function collapseWhitespaceSmart(str: string, prevTag: string, nextTag:
36
76
  preserveLineBreaks?: boolean;
37
77
  conservativeCollapse?: boolean;
38
78
  collapseInlineTagWhitespace?: boolean;
39
- }, inlineElements: Set<string>, inlineTextSet: Set<string>): string;
79
+ }, inlineSets: InlineSets): string;
40
80
  /** @param {string} tag */
41
81
  declare function canCollapseWhitespace(tag: string): boolean;
42
82
  /** @param {string} tag */
43
83
  declare function canTrimWhitespace(tag: string): boolean;
44
- export { trimWhitespace, collapseWhitespaceAll, collapseWhitespace, collapseWhitespaceSmart, canCollapseWhitespace, canTrimWhitespace };
84
+ export { buildInlineSets, defaultInlineSets, endsWithWhitespace, trimWhitespace, collapseWhitespaceAll, collapseWhitespace, collapseWhitespaceSmart, canCollapseWhitespace, canTrimWhitespace };
45
85
  //# sourceMappingURL=whitespace.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../../src/lib/whitespace.js"],"names":[],"mappings":"AAAA;;GAEG;AAqBH,0BAA0B;AAC1B,QAAA,MAAM,cAAc,QADR,MAAM,WAQjB,CAAC;AAuBF,0BAA0B;AAC1B,iBAAS,qBAAqB,CAAC,GAAG,EADtB,MACsB,UAOjC;AAeD;;;;;;GAMG;AACH,iBAAS,kBAAkB,CAAC,GAAG,EANpB,MAMoB,EAAE,OAAO,EAL7B;IAAC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAKxD,EAAE,QAAQ,EAJvC,OAIuC,EAAE,SAAS,EAHlD,OAGkD,EAAE,WAAW,AAFvE,CAA8B,EAAtB,OAEuE,UAcjF;AAsHD;;;;;;;;;GASG;AACH,iBAAS,uBAAuB,CAAC,GAAG,EATzB,MASyB,EAAE,OAAO,EARlC,MAQkC,EAAE,OAAO,EAP3C,MAO2C,EAAE,SAAS,EANtD,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAC,CAMkB,EAAE,SAAS,EALjE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAC,CAK6B,EAAE,OAAO,EAJ1E;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAAC,2BAA2B,CAAC,EAAE,OAAO,CAAA;CAI1B,EAAE,cAAc,EAH1F,GAAG,CAAC,MAAM,CAGgF,EAAE,aAAa,EAFzG,GAAG,CAAC,MAAM,CAE+F,UA6DnH;AAcD,0BAA0B;AAC1B,iBAAS,qBAAqB,CAAC,GAAG,EADtB,MACsB,WAEjC;AAED,0BAA0B;AAC1B,iBAAS,iBAAiB,CAAC,GAAG,EADlB,MACkB,WAE7B;AAID,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EAClB,CAAC"}
1
+ {"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../../src/lib/whitespace.js"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,0BAA0B;AAC1B,QAAA,MAAM,cAAc,QADR,MAAM,WAQjB,CAAC;AAaF,0BAA0B;AAC1B,iBAAS,kBAAkB,CAAC,GAAG,EADnB,MACmB,WAE9B;AAaD,0BAA0B;AAC1B,iBAAS,qBAAqB,CAAC,GAAG,EADtB,MACsB,UAOjC;AAoBD;;;;;;GAMG;AACH,iBAAS,kBAAkB,CAAC,GAAG,EANpB,MAMoB,EAAE,OAAO,EAL7B;IAAC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAKxD,EAAE,QAAQ,EAJvC,OAIuC,EAAE,SAAS,EAHlD,OAGkD,EAAE,WAAW,AAFvE,CAA8B,EAAtB,OAEuE,UAcjF;AAwGE,YAAkB,UAAU,GAC5B;;;;IAAoB,MAAM,EAAnB,GAAG,CAAC,MAAM,CAAC,CAClB;;;;IAAoB,SAAS,EAAtB,GAAG,CAAC,MAAM,CAAC,CAClB;;;;IAAoB,MAAM,EAAnB,GAAG,CAAC,MAAM,CAAC,CAClB;;;;IAAoB,SAAS,EAAtB,GAAG,CAAC,MAAM,CAAC,CAClB;;;;IAAoB,YAAY,EAAzB,GAAG,CAAC,MAAM,CAAC,CACpB;CAAA,CAAA;AAPD;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,iBAAS,eAAe,CAAC,MAAM,EAJpB,GAAG,CAAC,MAAM,CAIU,EAAE,MAAM,EAH5B,GAAG,CAAC,MAAM,CAGkB,GAF1B,UAAU,CAWtB;AAGD,QAAA,MAAM,iBAAiB,YAA8F,CAAC;AAiBtH;;;;;;;;GAQG;AACH,iBAAS,uBAAuB,CAAC,GAAG,EARzB,MAQyB,EAAE,OAAO,EAPlC,MAOkC,EAAE,OAAO,EAN3C,MAM2C,EAAE,SAAS,EALtD,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAC,CAKkB,EAAE,SAAS,EAJjE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAC,CAI6B,EAAE,OAAO,EAH1E;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAAC,2BAA2B,CAAC,EAAE,OAAO,CAAA;CAG1B,EAAE,UAAU,EAFtF,UAEsF,UA6DhG;AASD,0BAA0B;AAC1B,iBAAS,qBAAqB,CAAC,GAAG,EADtB,MACsB,WAEjC;AAED,0BAA0B;AAC1B,iBAAS,iBAAiB,CAAC,GAAG,EADlB,MACkB,WAE7B;AAID,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EAClB,CAAC"}
@@ -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
@@ -14,11 +14,11 @@
14
14
  },
15
15
  "description": "Highly effective, super-configurable, well-tested web page minifier (enhanced successor to HTML Minifier)",
16
16
  "devDependencies": {
17
- "@commitlint/cli": "^21.2.2",
17
+ "@commitlint/cli": "^21.2.3",
18
18
  "@eslint/js": "^10.0.1",
19
19
  "@swc/core": "^1.16.2",
20
- "@types/node": "^26.5.1",
21
- "eslint": "^10.10.0",
20
+ "@types/node": "^26.6.2",
21
+ "eslint": "^10.11.0",
22
22
  "globals": "^17.12.0",
23
23
  "typescript": "^7.0.2",
24
24
  "vite": "^8.3.0"
@@ -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.3"
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
 
@@ -32,6 +32,9 @@ import {
32
32
  } from './lib/constants.js';
33
33
 
34
34
  import {
35
+ buildInlineSets,
36
+ defaultInlineSets,
37
+ endsWithWhitespace,
35
38
  trimWhitespace,
36
39
  collapseWhitespaceAll,
37
40
  collapseWhitespace,
@@ -297,7 +300,8 @@ import { toFragment, replaceCustomFragments } from './lib/fragments.js';
297
300
  *
298
301
  * @prop {number} [maxLineLength]
299
302
  * Maximum line length for the output. When set the minifier will wrap
300
- * output to the given number of characters where possible.
303
+ * output to the given number of characters where possible, splitting
304
+ * lines only in tags—between attributes or before a tag’s `>`.
301
305
  *
302
306
  * Default: No limit
303
307
  *
@@ -350,8 +354,8 @@ import { toFragment, replaceCustomFragments } from './lib/fragments.js';
350
354
  * Default: `false`
351
355
  *
352
356
  * @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).
357
+ * When wrapping lines, never split a line in an end tag (e.g., keeps
358
+ * `</a>` from becoming `</a` and `>` on two lines).
355
359
  *
356
360
  * Default: `false`
357
361
  *
@@ -1047,6 +1051,8 @@ async function minifyHTML(value, options, partialMarkup) {
1047
1051
 
1048
1052
  /** @type {string[]} */
1049
1053
  const buffer = [];
1054
+ // Parallel to `buffer`: whether an entry belongs to a start or end tag, the only place lines may break
1055
+ const bufferTags = options.maxLineLength ? /** @type {boolean[]} */ ([]) : null;
1050
1056
  /** @type {string} */
1051
1057
  let charsPrevTag = '';
1052
1058
  let currentChars = '';
@@ -1099,6 +1105,9 @@ async function minifyHTML(value, options, partialMarkup) {
1099
1105
  const inlineElements = normalizedCustomElements.length
1100
1106
  ? new Set([...inlineElementsToKeepWhitespaceAround, ...normalizedCustomElements])
1101
1107
  : inlineElementsToKeepWhitespaceAround;
1108
+ const inlineSets = normalizedCustomElements.length
1109
+ ? buildInlineSets(inlineElements, inlineTextSet)
1110
+ : defaultInlineSets;
1102
1111
 
1103
1112
  // Parse `removeEmptyElementsExcept` option
1104
1113
  /** @type {Array<{tag: string, attrs: {[x: string]: string | undefined} | null}>} */
@@ -1278,12 +1287,22 @@ async function minifyHTML(value, options, partialMarkup) {
1278
1287
  return options.canTrimWhitespace(tag, attrs, defaultCanTrimWhitespace);
1279
1288
  }
1280
1289
 
1290
+ function bufferPush(/** @type {string} */ entry, /** @type {boolean} */ isTag) {
1291
+ buffer.push(entry);
1292
+ bufferTags?.push(isTag);
1293
+ }
1294
+
1295
+ function bufferTruncate(/** @type {number} */ length) {
1296
+ buffer.length = Math.max(0, length);
1297
+ if (bufferTags) bufferTags.length = buffer.length;
1298
+ }
1299
+
1281
1300
  function removeStartTag() {
1282
1301
  let index = buffer.length - 1;
1283
1302
  while (index > 0 && !RE_START_TAG.test(buffer[index] ?? '')) {
1284
1303
  index--;
1285
1304
  }
1286
- buffer.length = Math.max(0, index);
1305
+ bufferTruncate(index);
1287
1306
  }
1288
1307
 
1289
1308
  // Whether the element being parsed holds text rather than markup. The namespace decides
@@ -1339,24 +1358,39 @@ async function minifyHTML(value, options, partialMarkup) {
1339
1358
  const noTrim = stackNoTrimWhitespace.length > 0;
1340
1359
  if (index < buffer.length - 1 && (keepsWhitespace() || noTrim) && RE_END_TAG.test(buffer[index] ?? '')) {
1341
1360
  buffer.splice(index, 1);
1361
+ bufferTags?.splice(index, 1);
1342
1362
  // Only collapsed whitespace can merge
1343
1363
  if (options.collapseWhitespace && !noTrim) {
1344
1364
  mergeWhitespaceRuns(index);
1345
1365
  }
1346
1366
  return;
1347
1367
  }
1348
- buffer.length = Math.max(0, index);
1368
+ bufferTruncate(index);
1349
1369
  }
1350
1370
 
1351
1371
  // Look for trailing whitespaces, bypass any inline tags
1352
1372
  function trimTrailingWhitespace(/** @type {number} */ index, /** @type {string} */ nextTag) {
1373
+ // Nothing to the left of the text is in play here, so only its trailing run can
1374
+ // change—unless preserved line breaks bring the leading run into play, too
1375
+ const trailingOnly = !options.preserveLineBreaks;
1353
1376
  for (let prevTag = ''; index >= 0 && canTrimWhitespace(prevTag, emptyAttrs); index--) {
1354
1377
  const str = buffer[index] ?? '';
1355
1378
  const endTagName = matchPlainEndTag(str);
1356
1379
  if (endTagName !== null) {
1357
1380
  prevTag = endTagName;
1358
- } else if (str.charCodeAt(str.length - 1) === 62 /* > */ ||
1359
- (buffer[index] = collapseWhitespaceSmart(str, '', nextTag, emptyAttrs, emptyAttrs, options, inlineElements, inlineTextSet))) {
1381
+ continue;
1382
+ }
1383
+ // A tag ends the search, and so does text that survives collapsing. Text with no
1384
+ // trailing run comes back from the call unchanged, so it can end the search on
1385
+ // the spot; empty text cannot, as the search has to carry on past it
1386
+ if (str.charCodeAt(str.length - 1) === 62 /* > */) {
1387
+ break;
1388
+ }
1389
+ if (trailingOnly && str && !endsWithWhitespace(str)) {
1390
+ break;
1391
+ }
1392
+ buffer[index] = collapseWhitespaceSmart(str, '', nextTag, emptyAttrs, emptyAttrs, options, inlineSets);
1393
+ if (buffer[index]) {
1360
1394
  break;
1361
1395
  }
1362
1396
  }
@@ -1372,7 +1406,9 @@ async function minifyHTML(value, options, partialMarkup) {
1372
1406
  // minification run then removes
1373
1407
  while (charsIndex > 0) {
1374
1408
  const item = buffer[charsIndex] ?? '';
1375
- if (!/^(?:<!|$)/.test(item) || (uidIgnore && item.indexOf(uidIgnore) !== -1)) {
1409
+ // Comments and empty entries only, as `<!…` or nothing at all
1410
+ const skippable = item === '' || (item.charCodeAt(0) === 60 /* < */ && item.charCodeAt(1) === 33 /* ! */);
1411
+ if (!skippable || (uidIgnore && item.indexOf(uidIgnore) !== -1)) {
1376
1412
  break;
1377
1413
  }
1378
1414
  charsIndex--;
@@ -1459,12 +1495,12 @@ async function minifyHTML(value, options, partialMarkup) {
1459
1495
  }
1460
1496
  trimTrailingWhitespace(tagIndex - 1, 'br');
1461
1497
  }
1462
- } else if (inlineTextSet.has(textPrevTag.charAt(0) === '/' ? textPrevTag.slice(1) : textPrevTag)) {
1498
+ } else if (inlineSets.withinEither.has(textPrevTag)) {
1463
1499
  text = collapseWhitespace(text, options, /(?:^|\s)$/.test(currentChars), false);
1464
1500
  }
1465
1501
  }
1466
1502
  if (textPrevTag || textNextTag) {
1467
- text = collapseWhitespaceSmart(text, effectivePrevTag, textNextTag, textPrevAttrs, textNextAttrs, options, inlineElements, inlineTextSet);
1503
+ text = collapseWhitespaceSmart(text, effectivePrevTag, textNextTag, textPrevAttrs, textNextAttrs, options, inlineSets);
1468
1504
  } else {
1469
1505
  text = collapseWhitespace(text, options, true, true);
1470
1506
  }
@@ -1545,7 +1581,7 @@ async function minifyHTML(value, options, partialMarkup) {
1545
1581
  if (text) {
1546
1582
  hasChars = true;
1547
1583
  }
1548
- buffer.push(text);
1584
+ bufferPush(text, false);
1549
1585
  }
1550
1586
 
1551
1587
  // Comment finalization (sync): Optional tag handling, `htmlmin:ignore` whitespace collapsing, buffer push
@@ -1656,7 +1692,7 @@ async function minifyHTML(value, options, partialMarkup) {
1656
1692
  }
1657
1693
  }
1658
1694
 
1659
- buffer.push(comment);
1695
+ bufferPush(comment, false);
1660
1696
  }
1661
1697
 
1662
1698
  // Inline scripts are minified one at a time as the parse reaches them, which serializes
@@ -1839,7 +1875,7 @@ async function minifyHTML(value, options, partialMarkup) {
1839
1875
  const needsXMLSlash = unary && Boolean(options.insideSVG) && Boolean(options.minifySVG);
1840
1876
  const hasUnarySlash = needsXMLSlash || (unarySlash && (useNameParentForTag ? optionsParent : options).keepClosingSlash);
1841
1877
 
1842
- buffer.push(openTag);
1878
+ bufferPush(openTag, true);
1843
1879
 
1844
1880
  const fragmentJoinsTag = uidAttrExactPattern ? joinFragmentAttrs(attrs) : false;
1845
1881
  // Whatever runs into the tag name has to stay first
@@ -1883,7 +1919,7 @@ async function minifyHTML(value, options, partialMarkup) {
1883
1919
  }
1884
1920
  if (lastKeptIndex !== -1) {
1885
1921
  if (!fragmentJoinsTag) {
1886
- buffer.push(' ');
1922
+ bufferPush(' ', true);
1887
1923
  }
1888
1924
  for (let i = 0; i <= lastKeptIndex; i++) {
1889
1925
  const normalizedAttr = normalizedAttrs[i];
@@ -1893,7 +1929,11 @@ async function minifyHTML(value, options, partialMarkup) {
1893
1929
  }
1894
1930
  const builtAttr = buildAttr(normalizedAttr, hasUnarySlash, options, i === lastKeptIndex, uidAttr);
1895
1931
  // 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);
1932
+ if (i === 0 && fragmentJoinsTag) {
1933
+ buffer[buffer.length - 1] += builtAttr;
1934
+ } else {
1935
+ bufferPush(builtAttr, true);
1936
+ }
1897
1937
  }
1898
1938
  }
1899
1939
  } else if (optional && optionalStartTags.has(tag)) {
@@ -1901,7 +1941,7 @@ async function minifyHTML(value, options, partialMarkup) {
1901
1941
  optionalStartTag = tag;
1902
1942
  }
1903
1943
 
1904
- buffer.push(buffer.pop() + (hasUnarySlash ? '/' : '') + '>');
1944
+ buffer[buffer.length - 1] += (hasUnarySlash ? '/' : '') + '>';
1905
1945
 
1906
1946
  if (autoGenerated && !options.includeAutoGeneratedTags) {
1907
1947
  removeStartTag();
@@ -2010,7 +2050,7 @@ async function minifyHTML(value, options, partialMarkup) {
2010
2050
  if (autoGenerated && !options.includeAutoGeneratedTags) {
2011
2051
  optionalEndTagEmitted = false;
2012
2052
  } else {
2013
- buffer.push(endTagText);
2053
+ bufferPush(endTagText, true);
2014
2054
  }
2015
2055
  charsPrevTag = '/' + tag;
2016
2056
  if (!inlineElements.has(tag)) {
@@ -2023,7 +2063,7 @@ async function minifyHTML(value, options, partialMarkup) {
2023
2063
  if (autoGenerated && !options.includeAutoGeneratedTags) {
2024
2064
  optionalEndTagEmitted = false;
2025
2065
  } else {
2026
- buffer.push(endTagText);
2066
+ bufferPush(endTagText, true);
2027
2067
  }
2028
2068
  charsPrevTag = '/' + tag;
2029
2069
  if (!inlineElements.has(tag)) {
@@ -2099,10 +2139,10 @@ async function minifyHTML(value, options, partialMarkup) {
2099
2139
  commentFinalize(text);
2100
2140
  },
2101
2141
  doctype: function (/** @type {string} */ doctype) {
2102
- buffer.push(options.useShortDoctype
2142
+ bufferPush(options.useShortDoctype
2103
2143
  ? '<!doctype' +
2104
2144
  (options.removeTagWhitespace ? '' : ' ') + 'html>'
2105
- : collapseWhitespaceAll(doctype));
2145
+ : collapseWhitespaceAll(doctype), false);
2106
2146
  }
2107
2147
  });
2108
2148
 
@@ -2119,7 +2159,10 @@ async function minifyHTML(value, options, partialMarkup) {
2119
2159
  );
2120
2160
  for (let i = svgBlocks.length - 1; i >= 0; i--) {
2121
2161
  const block = svgBlocks[i];
2122
- if (block) buffer.splice(block.start, block.end - block.start, optimized[i] ?? '');
2162
+ if (block) {
2163
+ buffer.splice(block.start, block.end - block.start, optimized[i] ?? '');
2164
+ bufferTags?.splice(block.start, block.end - block.start, false);
2165
+ }
2123
2166
  }
2124
2167
  }
2125
2168
 
@@ -2138,7 +2181,7 @@ async function minifyHTML(value, options, partialMarkup) {
2138
2181
  squashTrailingWhitespace('br');
2139
2182
  }
2140
2183
 
2141
- return joinResultSegments(buffer, options, uidPattern
2184
+ return joinResultSegments(buffer, bufferTags ?? [], [uidAttr, uidIgnore].filter(marker => marker !== undefined), options, uidPattern
2142
2185
  ? function (/** @type {string} */ str) {
2143
2186
  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
2187
  const chunks = ignoredCustomMarkupChunks[+index];
@@ -2173,46 +2216,74 @@ async function minifyHTML(value, options, partialMarkup) {
2173
2216
 
2174
2217
  /**
2175
2218
  * @param {string[]} results
2219
+ * @param {boolean[]} resultTags Whether each result belongs to a start or end tag
2220
+ * @param {string[]} markers Custom fragment and `htmlmin:ignore` placeholder markers
2176
2221
  * @param {ProcessedOptions} options
2177
2222
  * @param {Function} restoreCustom
2178
2223
  * @param {Function} restoreIgnore
2179
2224
  */
2180
- function joinResultSegments(results, options, restoreCustom, restoreIgnore) {
2225
+ function joinResultSegments(results, resultTags, markers, options, restoreCustom, restoreIgnore) {
2181
2226
  let str;
2182
2227
  const maxLineLength = options.maxLineLength;
2183
- const noNewlinesBeforeTagClose = options.noNewlinesBeforeTagClose;
2184
2228
 
2185
2229
  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);
2230
+ // Whitespace in tags is the only whitespace that can’t change the output, so lines break
2231
+ // there alone—in place of the space between attributes, or right before a tag’s `>`
2232
+ const noNewlinesBeforeTagClose = options.noNewlinesBeforeTagClose;
2233
+ /** @type {string[]} */
2234
+ const lines = [];
2235
+ let lineLength = 0;
2236
+ // Output since the last break opportunity, and what that opportunity is when not taken;
2237
+ // fragments are restored by chunk, as whitespace around them decides how they come back
2238
+ let chunk = '';
2239
+ /** @type {string | null} */
2240
+ let separator = null;
2241
+ const flush = (/** @type {string | null} */ nextSeparator) => {
2242
+ chunk = restoreIgnore(restoreCustom(chunk));
2243
+ const newline = chunk.indexOf('\n');
2244
+ const head = newline < 0 ? chunk.length : newline;
2245
+ // A line already too long gains nothing from moving a `>` that ends a line of its own
2246
+ const isUseless = separator === '' && head === 1 && lineLength > maxLineLength;
2247
+ if (separator !== null) {
2248
+ if (lineLength > 0 && lineLength + separator.length + head > maxLineLength && !isUseless) {
2249
+ lines.push('\n');
2250
+ lineLength = 0;
2251
+ } else if (separator) {
2252
+ lines.push(separator);
2253
+ lineLength += separator.length;
2254
+ }
2203
2255
  }
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 = '';
2256
+ lines.push(chunk);
2257
+ lineLength = newline < 0 ? lineLength + chunk.length : chunk.length - chunk.lastIndexOf('\n') - 1;
2258
+ chunk = '';
2259
+ separator = nextSeparator;
2260
+ };
2261
+ for (let index = 0; index < results.length; index++) {
2262
+ const result = results[index] ?? '';
2263
+ if (!resultTags[index]) {
2264
+ chunk += result;
2265
+ } else if (markers.length && markers.some(marker => result.includes(marker))) {
2266
+ // Whitespace next to a fragment stays as is, as it may belong to it
2267
+ if (!chunk && separator !== null) {
2268
+ chunk = separator;
2269
+ separator = null;
2270
+ }
2271
+ chunk += result;
2272
+ } else if (result.charCodeAt(result.length - 1) === 32 /* space */) {
2273
+ chunk += result.slice(0, -1);
2274
+ flush(' ');
2275
+ } else if (result.charCodeAt(result.length - 1) === 62 /* > */ &&
2276
+ result.charCodeAt(result.length - 2) !== 47 /* / */ &&
2277
+ !(noNewlinesBeforeTagClose && result.startsWith('</'))) {
2278
+ chunk += result.slice(0, -1);
2279
+ flush('');
2280
+ chunk = '>';
2281
+ } else {
2282
+ chunk += result;
2210
2283
  }
2211
2284
  }
2212
- if (line) {
2213
- lines.push(line);
2214
- }
2215
- str = lines.join('\n');
2285
+ flush(null);
2286
+ str = lines.join('');
2216
2287
  } else {
2217
2288
  str = restoreIgnore(restoreCustom(results.join('')));
2218
2289
  }
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) {
@@ -50,6 +50,15 @@ const inlineElementsToKeepWhitespace = new Set(['comment', 'img', 'input', 'wbr'
50
50
  // Form control elements (for conditional whitespace collapsing)
51
51
  const formControlElements = new Set(['input', 'button', 'select', 'textarea', 'output', 'meter', 'progress']);
52
52
 
53
+ // End-tag spellings (`/a`) of a set of element names
54
+ /** @param {Iterable<string>} names */
55
+ const toEndTags = names => new Set(Array.from(names, name => '/' + name));
56
+
57
+ // Membership under either spelling, for the whitespace checks that ignore the slash;
58
+ // looking a tag up as it comes keeps the hot path from slicing one string per call
59
+ const inlineElementsToKeepWhitespaceWithinEither = new Set([...inlineElementsToKeepWhitespaceWithin, ...toEndTags(inlineElementsToKeepWhitespaceWithin)]);
60
+ const formControlElementsEither = new Set([...formControlElements, ...toEndTags(formControlElements)]);
61
+
53
62
  // Default attribute values
54
63
 
55
64
  // Default attribute values (could apply to any element)
@@ -285,7 +294,9 @@ export {
285
294
  inlineElementsToKeepWhitespaceAround,
286
295
  inlineElementsToKeepWhitespaceWithin,
287
296
  inlineElementsToKeepWhitespace,
288
- formControlElements,
297
+ inlineElementsToKeepWhitespaceWithinEither,
298
+ formControlElementsEither,
299
+ toEndTags,
289
300
 
290
301
  // Default values
291
302
  generalDefaults,
@@ -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: {
@@ -9,14 +9,18 @@ import {
9
9
  RE_NBSP_TRAILING_GROUP,
10
10
  RE_NBSP_TRAILING_STRIP,
11
11
  inlineElementsToKeepWhitespace,
12
+ inlineElementsToKeepWhitespaceAround,
12
13
  inlineElementsToKeepWhitespaceWithin,
13
- formControlElements
14
+ inlineElementsToKeepWhitespaceWithinEither,
15
+ formControlElementsEither,
16
+ toEndTags
14
17
  } from './constants.js';
15
18
 
16
19
  const RE_ANY_WS_NBSP = /[ \n\r\t\f\xA0]/;
17
20
  const RE_TAB_NBSP = /[\t\xA0]/;
18
21
  const RE_ASCII_WS_RUN = /[ \n\r\f]+/g;
19
- const RE_NEEDS_COLLAPSE = /[\n\r\f]| {2}/;
22
+ // Every reason `collapseWhitespaceAllKnown` has to do any work at all, in one scan
23
+ const RE_COLLAPSIBLE = /[\t\xA0\n\r\f]| {2}/;
20
24
  const RE_NON_WS = /\S/;
21
25
 
22
26
  // Trim whitespace
@@ -41,6 +45,12 @@ function isWsOrNbsp(code) {
41
45
  return code === 32 || code === 10 || code === 13 || code === 9 || code === 12 || code === 160;
42
46
  }
43
47
 
48
+ // Whether the last character is whitespace, no-break space included
49
+ /** @param {string} str */
50
+ function endsWithWhitespace(str) {
51
+ return str.length > 0 && isWsOrNbsp(str.charCodeAt(str.length - 1));
52
+ }
53
+
44
54
  // Collapse all whitespace
45
55
 
46
56
  // Module scope so the hot path doesn’t allocate a closure per call
@@ -65,10 +75,15 @@ function collapseWhitespaceAll(str) {
65
75
  // As `collapseWhitespaceAll`, for callers that already know `str` holds whitespace
66
76
  /** @param {string} str */
67
77
  function collapseWhitespaceAllKnown(str) {
78
+ // Most text reaching here is already collapsed, so settle that in one scan rather
79
+ // than two—single spaces with no tab and no no-break space leave nothing to do
80
+ if (!RE_COLLAPSIBLE.test(str)) {
81
+ return str;
82
+ }
68
83
  // Only a tab or a no-break space makes the replacement depend on the run itself;
69
84
  // without either, every run becomes one space and no per-match callback is needed
70
85
  if (!RE_TAB_NBSP.test(str)) {
71
- return RE_NEEDS_COLLAPSE.test(str) ? str.replace(RE_ASCII_WS_RUN, ' ') : str;
86
+ return str.replace(RE_ASCII_WS_RUN, ' ');
72
87
  }
73
88
  return str.replace(RE_ALL_WS_NBSP, collapseRun);
74
89
  }
@@ -199,6 +214,36 @@ function collapseWhitespaceKnown(str, options, trimLeft, trimRight, collapseAll)
199
214
 
200
215
  // Collapse whitespace smartly based on surrounding tags
201
216
 
217
+ /**
218
+ * @typedef {object} InlineSets
219
+ * @prop {Set<string>} around - Elements whose surrounding whitespace is kept
220
+ * @prop {Set<string>} aroundEnd - The same, spelled as end tags
221
+ * @prop {Set<string>} within - Elements whose inner whitespace is kept
222
+ * @prop {Set<string>} withinEnd - The same, spelled as end tags
223
+ * @prop {Set<string>} withinEither - `within` under both spellings
224
+ */
225
+
226
+ /**
227
+ * Inline-element membership for the whitespace pass, each set paired with its end-tag
228
+ * spelling so a lookup takes the tag as it comes rather than slicing off the slash
229
+ * @param {Set<string>} around
230
+ * @param {Set<string>} within
231
+ * @returns {InlineSets}
232
+ */
233
+ function buildInlineSets(around, within) {
234
+ const withinEnd = toEndTags(within);
235
+ return {
236
+ around,
237
+ aroundEnd: toEndTags(around),
238
+ within,
239
+ withinEnd,
240
+ withinEither: new Set([...within, ...withinEnd])
241
+ };
242
+ }
243
+
244
+ // The sets for a document without custom inline elements, built once
245
+ const defaultInlineSets = buildInlineSets(inlineElementsToKeepWhitespaceAround, inlineElementsToKeepWhitespaceWithin);
246
+
202
247
  // Check if an input element has `type="hidden"`; module-scope so the hot path
203
248
  // doesn’t allocate a closure per text node
204
249
  /**
@@ -221,10 +266,9 @@ function isHiddenInput(attrs) {
221
266
  * @param {Array<{name: string, value?: string}>} prevAttrs
222
267
  * @param {Array<{name: string, value?: string}>} nextAttrs
223
268
  * @param {{preserveLineBreaks?: boolean, conservativeCollapse?: boolean, collapseInlineTagWhitespace?: boolean}} options
224
- * @param {Set<string>} inlineElements
225
- * @param {Set<string>} inlineTextSet
269
+ * @param {InlineSets} inlineSets
226
270
  */
227
- function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, options, inlineElements, inlineTextSet) {
271
+ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, options, inlineSets) {
228
272
  if (!str) return str;
229
273
 
230
274
  // Fast path: No whitespace at all—every decision below would leave `str`
@@ -253,7 +297,7 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
253
297
  }
254
298
  // Aggressive mode: Collapse between all form controls
255
299
  if (inlineOption && (!trimLeft || !trimRight) &&
256
- formControlElements.has(stripSlash(prevTag)) && formControlElements.has(stripSlash(nextTag))) {
300
+ formControlElementsEither.has(prevTag) && formControlElementsEither.has(nextTag)) {
257
301
  trimLeft = true;
258
302
  trimRight = true;
259
303
  }
@@ -262,21 +306,21 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
262
306
  if (trimLeft) {
263
307
  if (inlineOption) {
264
308
  // Still preserve whitespace around inline text elements
265
- if (inlineElementsToKeepWhitespaceWithin.has(stripSlash(prevTag))) {
309
+ if (inlineElementsToKeepWhitespaceWithinEither.has(prevTag)) {
266
310
  trimLeft = false;
267
311
  }
268
312
  } else {
269
- trimLeft = prevTag.charCodeAt(0) === 47 /* / */ ? !inlineElements.has(prevTag.slice(1)) : !inlineTextSet.has(prevTag);
313
+ trimLeft = prevTag.charCodeAt(0) === 47 /* / */ ? !inlineSets.aroundEnd.has(prevTag) : !inlineSets.within.has(prevTag);
270
314
  }
271
315
  }
272
316
 
273
317
  if (trimRight) {
274
318
  if (inlineOption) {
275
- if (inlineElementsToKeepWhitespaceWithin.has(stripSlash(nextTag))) {
319
+ if (inlineElementsToKeepWhitespaceWithinEither.has(nextTag)) {
276
320
  trimRight = false;
277
321
  }
278
322
  } else {
279
- trimRight = nextTag.charCodeAt(0) === 47 /* / */ ? !inlineTextSet.has(nextTag.slice(1)) : !inlineElements.has(nextTag);
323
+ trimRight = nextTag.charCodeAt(0) === 47 /* / */ ? !inlineSets.withinEnd.has(nextTag) : !inlineSets.around.has(nextTag);
280
324
  }
281
325
  }
282
326
 
@@ -287,11 +331,6 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
287
331
  return collapseWhitespaceKnown(str, options, trimLeft, trimRight, collapseAll);
288
332
  }
289
333
 
290
- /** @param {string} tag */
291
- function stripSlash(tag) {
292
- return tag && tag.charCodeAt(0) === 47 /* / */ ? tag.slice(1) : tag;
293
- }
294
-
295
334
  // Collapse/trim whitespace for given tag
296
335
 
297
336
  // `xmp`, `listing`, and `plaintext` render preformatted, as `pre` does
@@ -312,6 +351,9 @@ function canTrimWhitespace(tag) {
312
351
  // Exports
313
352
 
314
353
  export {
354
+ buildInlineSets,
355
+ defaultInlineSets,
356
+ endsWithWhitespace,
315
357
  trimWhitespace,
316
358
  collapseWhitespaceAll,
317
359
  collapseWhitespace,