html-minifier-next 8.4.1 → 8.4.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
@@ -241,7 +241,7 @@ Where the modifiers disagree, the preserving one wins—`conservativeCollapse` a
241
241
 
242
242
  ### Sorting attributes and style classes
243
243
 
244
- Minifier options like `sortAttributes` and `sortClassNames` won’t impact the plain-text size of the output. However, using these options for more consistent ordering improves the compression ratio for Gzip and Brotli used over HTTP.
244
+ Minifier options like `sortAttributes` and `sortClassNames` won’t impact the plain-text size of the output. However, `sortAttributes` (but not `sortClassNames`) improves the compression ratio for Gzip and Brotli used over HTTP.
245
245
 
246
246
  ### CSS minification
247
247
 
package/cli.js CHANGED
@@ -53,6 +53,7 @@ const commanderOptionKey = (key) => {
53
53
  import { getPreset, getPresetNames } from './src/presets.js';
54
54
  import { paramCase, parseRegExp } from './src/lib/utils.js';
55
55
  import { optionDefinitions } from './src/lib/option-definitions.js';
56
+ import { writeFileAtomic } from './src/lib/file-write.js';
56
57
 
57
58
  const pkg = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf8'));
58
59
 
@@ -681,7 +682,7 @@ program.helpOption('-h, --help', 'Display help for command');
681
682
  return { originalSize: stats.originalSize, minifiedSize: stats.minifiedSize, saved: stats.saved };
682
683
  }
683
684
 
684
- await fs.promises.writeFile(outputFile, minified, { encoding: 'utf8' }).catch(err => {
685
+ await writeFileAtomic(outputFile, minified).catch(err => {
685
686
  fatal('Cannot write ' + outputFile + '\n' + err.message);
686
687
  });
687
688
 
@@ -1000,7 +1001,7 @@ program.helpOption('-h, --help', 'Display help for command');
1000
1001
  if (programOptions.output) {
1001
1002
  try {
1002
1003
  await fs.promises.mkdir(path.dirname(programOptions.output), { recursive: true });
1003
- await fs.promises.writeFile(programOptions.output, minified, { encoding: 'utf8' });
1004
+ await writeFileAtomic(programOptions.output, minified);
1004
1005
  } catch (err) {
1005
1006
  fatal('Cannot write ' + programOptions.output + '\n' + errorMessage(err));
1006
1007
  }
@@ -1188,7 +1189,7 @@ program.helpOption('-h, --help', 'Display help for command');
1188
1189
  if (programOptions.output) {
1189
1190
  try {
1190
1191
  await fs.promises.mkdir(path.dirname(programOptions.output), { recursive: true });
1191
- await fs.promises.writeFile(programOptions.output, minifiedCombined, 'utf8');
1192
+ await writeFileAtomic(programOptions.output, minifiedCombined);
1192
1193
  } catch (err) {
1193
1194
  fatal('Cannot write ' + programOptions.output + '\n' + errorMessage(err));
1194
1195
  }
@@ -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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"}
@@ -106,5 +106,6 @@ declare const genericRawTextElements: Set<string>;
106
106
  declare const endlessRawTextElements: Set<string>;
107
107
  declare const escapableRawTextElements: Set<string>;
108
108
  declare const rawTextElements: Set<string>;
109
- 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, optionalStartTags, optionalEndTags, headerElements, descriptionElements, pBlockElements, pInlineElements, rubyEndTagOmission, rubyRtcEndTagOmission, optionElements, tableContentElements, tableSectionElements, cellElements, topLevelElements, compactElements, looseElements, trailingElements, htmlElements, specialContentElements, genericRawTextElements, endlessRawTextElements, escapableRawTextElements, rawTextElements };
109
+ declare const MISSING_DEPENDENCY = "HMN_MISSING_DEPENDENCY";
110
+ 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, optionalStartTags, optionalEndTags, headerElements, descriptionElements, pBlockElements, pInlineElements, rubyEndTagOmission, rubyRtcEndTagOmission, optionElements, tableContentElements, tableSectionElements, cellElements, topLevelElements, compactElements, looseElements, trailingElements, htmlElements, specialContentElements, genericRawTextElements, endlessRawTextElements, escapableRawTextElements, rawTextElements };
110
111
  //# 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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/options.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/options.js"],"names":[],"mappings":"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"}
@@ -98,5 +98,16 @@ declare function describeQuantifierRisk(pattern: RegExp | string): string | null
98
98
  * @returns {number} Index of the closing `>`, or -1 if not found
99
99
  */
100
100
  declare function findTagEnd(html: string, pos: number, limit?: number): number;
101
- export { stableStringify, findTagEnd, LRU, MAX_CACHE_ENTRY_SIZE, hashContent, uniqueId, identity, isThenable, lowercase, paramCase, replaceAsync, parseRegExp, embedSource, lostFlag, describeQuantifierRisk };
101
+ /**
102
+ * A package that resolves but fails to load—e.g., a native binding built for
103
+ * another platform—is not one another `npm install` fixes, so name what happened
104
+ * rather than the install command
105
+ *
106
+ * @param {string} label - Minifier name as it should read in the message
107
+ * @param {string} specifier - Package that failed to load
108
+ * @param {unknown} cause - Error the import rejected with
109
+ * @returns {string} Message describing the failure
110
+ */
111
+ declare function describeDependencyFailure(label: string, specifier: string, cause: unknown): string;
112
+ export { stableStringify, findTagEnd, LRU, MAX_CACHE_ENTRY_SIZE, hashContent, uniqueId, identity, isThenable, lowercase, paramCase, replaceAsync, parseRegExp, embedSource, lostFlag, describeQuantifierRisk, describeDependencyFailure };
102
113
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;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;AAGD,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,CAe3B;AAID,qCAAqC;AACrC,iBAAS,WAAW,CAAC,KAAK,EADd,MAAM,GAAG,MACK,sBAUzB;AAyYD;;;;;;;;;GASG;AACH,iBAAS,QAAQ,CAAC,OAAO,EAJd,MAIc,GAHZ,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAqDlC;AAED;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,OAAO,EAHjB,MAGiB,GAFf,MAAM,CAOlB;AAGE,YAA6D,MAAM,GAAzD;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAA;CAAC,CAE7D;AAqKD;;;;;GAKG;AACH,iBAAS,sBAAsB,CAAC,OAAO,EAL5B,MAAM,GAAG,MAKmB,GAH1B,MAAM,GAAG,IAAI,CAqBzB;AAED;;;;;;;GAOG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,GAAG,EAJlB,MAIkB,EAAE,KAAK,AAHjC,CACA,EADQ,MAGuC,GAFrC,MAAM,CAelB;AAID,OAAO,EACL,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,sBAAsB,EACvB,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;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;AAGD,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,CAe3B;AAID,qCAAqC;AACrC,iBAAS,WAAW,CAAC,KAAK,EADd,MAAM,GAAG,MACK,sBAUzB;AAyYD;;;;;;;;;GASG;AACH,iBAAS,QAAQ,CAAC,OAAO,EAJd,MAIc,GAHZ,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAqDlC;AAED;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,OAAO,EAHjB,MAGiB,GAFf,MAAM,CAOlB;AAGE,YAA6D,MAAM,GAAzD;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAA;CAAC,CAE7D;AAqKD;;;;;GAKG;AACH,iBAAS,sBAAsB,CAAC,OAAO,EAL5B,MAAM,GAAG,MAKmB,GAH1B,MAAM,GAAG,IAAI,CAqBzB;AAED;;;;;;;GAOG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,GAAG,EAJlB,MAIkB,EAAE,KAAK,AAHjC,CACA,EADQ,MAGuC,GAFrC,MAAM,CAelB;AAED;;;;;;;;;GASG;AACH,iBAAS,yBAAyB,CAAC,KAAK,EAL7B,MAK6B,EAAE,SAAS,EAJxC,MAIwC,EAAE,KAAK,EAH/C,OAG+C,GAF7C,MAAM,CAYlB;AAID,OAAO,EACL,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,sBAAsB,EACtB,yBAAyB,EAC1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../../src/lib/whitespace.js"],"names":[],"mappings":"AAAA;;GAEG;AAiBH,0BAA0B;AAC1B,QAAA,MAAM,cAAc,QADR,MAAM,WAQjB,CAAC;AAIF,0BAA0B;AAC1B,iBAAS,qBAAqB,CAAC,GAAG,EADtB,MACsB,UAgBjC;AAID;;;;;;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,UAqFjF;AAoBD;;;;;;;;;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,UA4EnH;AASD,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;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"}
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.0",
20
+ "@types/node": "^26.5.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.4.1"
98
+ "version": "8.4.3"
99
99
  }
@@ -2,7 +2,7 @@ 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, findTagEnd, identity, isThenable, lowercase, uniqueId } from './lib/utils.js';
5
+ import { LRU, describeDependencyFailure, findTagEnd, identity, isThenable, lowercase, uniqueId } from './lib/utils.js';
6
6
  import { collectUsedSymbols } from './lib/unused-css.js';
7
7
 
8
8
  import {
@@ -26,7 +26,8 @@ import {
26
26
  compactElements,
27
27
  looseElements,
28
28
  trailingElements,
29
- pInlineElements
29
+ pInlineElements,
30
+ MISSING_DEPENDENCY
30
31
  } from './lib/constants.js';
31
32
 
32
33
  import {
@@ -516,17 +517,26 @@ async function getTerser() {
516
517
  return terserPromise;
517
518
  }
518
519
 
520
+ /**
521
+ * @param {string} label - Minifier name as it should read in the message
522
+ * @param {string} specifier - Package that failed to load
523
+ * @param {unknown} cause - Error the import rejected with
524
+ * @returns {Error} Error marked as an unavailable dependency
525
+ */
526
+ function unavailableDependency(label, specifier, cause) {
527
+ const err = new Error(describeDependencyFailure(label, specifier, cause), { cause });
528
+ /** @type {any} */ (err).code = MISSING_DEPENDENCY;
529
+ return err;
530
+ }
531
+
519
532
  /** @type {Promise<any> | undefined} */
520
533
  let swcPromise;
521
534
  async function getSwc() {
522
535
  if (!swcPromise) {
523
536
  swcPromise = import('@swc/core')
524
537
  .then(m => m.default || m)
525
- .catch(() => {
526
- throw new Error(
527
- 'The swc minifier requires @swc/core to be installed.\n' +
528
- 'Install it with: npm install @swc/core'
529
- );
538
+ .catch(err => {
539
+ throw unavailableDependency('swc', '@swc/core', err);
530
540
  });
531
541
  }
532
542
  return swcPromise;
@@ -207,6 +207,10 @@ const escapableRawTextElements = new Set(['textarea', 'title']);
207
207
  // of `textarea` and `title`, where they are resolved as they are anywhere else
208
208
  const rawTextElements = new Set([...specialContentElements, ...genericRawTextElements]);
209
209
 
210
+ // Marks the error for a minifier that was asked for but isn’t available—a
211
+ // configuration error, and so not one that `continueOnMinifyError` waves through
212
+ const MISSING_DEPENDENCY = 'HMN_MISSING_DEPENDENCY';
213
+
210
214
  // Exports
211
215
 
212
216
  export {
@@ -256,6 +260,7 @@ export {
256
260
 
257
261
  // Misc
258
262
  srcsetElements,
263
+ MISSING_DEPENDENCY,
259
264
 
260
265
  // Tag omission rules
261
266
  optionalStartTags,
@@ -21,6 +21,7 @@
21
21
 
22
22
  import fs from 'node:fs';
23
23
  import { isMainThread, parentPort, workerData, Worker } from 'node:worker_threads';
24
+ import { writeFileAtomic } from './file-write.js';
24
25
 
25
26
  // This module is its own worker entry point: The pool spawns it by URL and the branch
26
27
  // below runs in the spawned copy. Keeping both halves in one file keeps the message
@@ -61,7 +62,7 @@ if (!isMainThread && parentPort) {
61
62
  const minified = await minify(data, taskOptions);
62
63
  if (!task.dryRun) {
63
64
  stage = 'write';
64
- await fs.promises.writeFile(task.outputFile, minified, 'utf8');
65
+ await writeFileAtomic(task.outputFile, minified);
65
66
  }
66
67
  port.postMessage({
67
68
  id: task.id,
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Output writing for the CLI, shared by in-process runs and the worker pool
3
+ */
4
+
5
+ import crypto from 'node:crypto';
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ // A random name is taken by chance only, so a few attempts are plenty
10
+ const ATTEMPTS_MAX = 10;
11
+ // As many links as a system commonly follows before reporting a loop
12
+ const LINKS_MAX = 40;
13
+
14
+ /**
15
+ * The file a write replaces: the output itself or, for a symlink, the file it
16
+ * points to—followed by hand where that file does not exist yet, which
17
+ * `realpath` cannot resolve
18
+ * @param {string} outputFile
19
+ * @returns {Promise<string>}
20
+ */
21
+ async function resolveTarget(outputFile) {
22
+ let file = outputFile;
23
+ for (let i = 0; i < LINKS_MAX; i++) {
24
+ try {
25
+ return await fs.promises.realpath(file);
26
+ } catch {
27
+ const link = await fs.promises.readlink(file).catch(() => undefined);
28
+ if (link === undefined) return file;
29
+ // A relative link is read from the real location of its folder
30
+ const dir = await fs.promises.realpath(path.dirname(file)).catch(() => path.dirname(file));
31
+ file = path.resolve(dir, link);
32
+ }
33
+ }
34
+ // A loop, which writing through would not resolve, either—refused so the rename cannot replace the link
35
+ throw Object.assign(new Error(`ELOOP: Too many symbolic links encountered, '${outputFile}'`), { code: 'ELOOP', path: outputFile });
36
+ }
37
+
38
+ /**
39
+ * Create a temporary file next to the target under a random name, exclusively,
40
+ * so that it can neither be predicted nor write through a file or link already there
41
+ * @param {string} targetFile
42
+ * @param {number | undefined} mode
43
+ */
44
+ async function openTempFile(targetFile, mode) {
45
+ for (let attempt = 1; ; attempt++) {
46
+ const tempFile = path.join(path.dirname(targetFile), `.${path.basename(targetFile)}.${crypto.randomBytes(8).toString('hex')}.tmp`);
47
+ try {
48
+ return { tempFile, handle: await fs.promises.open(tempFile, 'wx', mode) };
49
+ } catch (err) {
50
+ if (/** @type {any} */ (err).code !== 'EEXIST' || attempt >= ATTEMPTS_MAX) throw err;
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Write a file by way of a temporary file in the same folder, so that an exit
57
+ * that leaves no chance to clean up—a native crash in a minifier, an OOM
58
+ * kill—cannot leave a half-written file where the output belongs
59
+ * @param {string} outputFile
60
+ * @param {string} data
61
+ */
62
+ export async function writeFileAtomic(outputFile, data) {
63
+ // A rename would replace a symlink itself, so work on the file it points to
64
+ const targetFile = await resolveTarget(outputFile);
65
+ // The rename replaces the output rather than writing through it, so a mode set on the output has to be carried over
66
+ const stats = await fs.promises.stat(targetFile).catch(() => undefined);
67
+ const mode = stats ? stats.mode & 0o7777 : undefined;
68
+
69
+ // Outside the `try`, so that only a file this write created is ever removed
70
+ const { tempFile, handle } = await openTempFile(targetFile, mode);
71
+
72
+ try {
73
+ try {
74
+ await handle.writeFile(data, 'utf8');
75
+ } finally {
76
+ await handle.close();
77
+ }
78
+ // `mode` on creation is subject to the umask, so the exact bits have to be set separately
79
+ if (mode !== undefined) {
80
+ await fs.promises.chmod(tempFile, mode);
81
+ }
82
+ await fs.promises.rename(tempFile, targetFile);
83
+ } catch (err) {
84
+ await fs.promises.rm(tempFile, { force: true });
85
+ throw err;
86
+ }
87
+ }
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { createUrlMinifier } from './urls.js';
6
6
  import { LRU, MAX_CACHE_ENTRY_SIZE, stableStringify, hashContent, identity, lowercase, paramCase, replaceAsync, parseRegExp, describeQuantifierRisk, lostFlag } from './utils.js';
7
- import { RE_TRAILING_SEMICOLON } from './constants.js';
7
+ import { RE_TRAILING_SEMICOLON, MISSING_DEPENDENCY } from './constants.js';
8
8
  import { canCollapseWhitespace, canTrimWhitespace } from './whitespace.js';
9
9
  import { wrapCSS, unwrapCSS } from './content.js';
10
10
  import { findUnusedSymbols, normalizeUnusedCSSOptions } from './unused-css.js';
@@ -152,6 +152,33 @@ function isRequested(value) {
152
152
  return Array.isArray(value) ? value.length > 0 : Boolean(value);
153
153
  }
154
154
 
155
+ /** @param {unknown} err - Error raised while minifying */
156
+ function isMissingDependency(err) {
157
+ return Boolean(err) && /** @type {any} */ (err).code === MISSING_DEPENDENCY;
158
+ }
159
+
160
+ // An unset (falsy) engine takes the fallback and names match lowercase; anything else
161
+ // passes through untouched so that validation reports it instead of a type error
162
+ /**
163
+ * @param {unknown} engine - Configured engine name
164
+ * @param {string} fallback - Engine to use when none is configured
165
+ */
166
+ function normalizeEngine(engine, fallback) {
167
+ if (!engine) return fallback;
168
+ return typeof engine === 'string' ? engine.toLowerCase() : engine;
169
+ }
170
+
171
+ /** @param {unknown} engine - Engine name as it should read in an error message */
172
+ function describeEngine(engine) {
173
+ if (typeof engine === 'string') return engine;
174
+ try {
175
+ return JSON.stringify(engine) ?? String(engine);
176
+ } catch {
177
+ // BigInt and cyclic values do not serialize
178
+ return String(engine);
179
+ }
180
+ }
181
+
155
182
  // Main options processor
156
183
 
157
184
  /**
@@ -433,12 +460,12 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
433
460
 
434
461
  // Parse configuration
435
462
  const config = typeof option === 'object' ? option : {};
436
- const engine = (config.engine || 'terser').toLowerCase();
463
+ const engine = normalizeEngine(config.engine, 'terser');
437
464
 
438
465
  // Validate engine
439
466
  const supportedEngines = ['terser', 'swc'];
440
- if (!supportedEngines.includes(engine)) {
441
- throw new Error(`Unsupported JS minifier engine: “${engine}”. Supported engines: ${supportedEngines.join(', ')}`);
467
+ if (!supportedEngines.includes(/** @type {string} */ (engine))) {
468
+ throw new Error(`Unsupported JS minifier engine: \`${describeEngine(engine)}\`. Supported engines: ${supportedEngines.join(', ')}`);
442
469
  }
443
470
 
444
471
  // Extract engine-specific options (excluding `engine` field itself)
@@ -530,7 +557,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
530
557
  return resolved;
531
558
  } catch (err) {
532
559
  if (jsKey !== undefined) jsCache.delete(jsKey);
533
- if (!options.continueOnMinifyError) {
560
+ if (!options.continueOnMinifyError || isMissingDependency(err)) {
534
561
  throw err;
535
562
  }
536
563
  options.log && options.log(err);
package/src/lib/utils.js CHANGED
@@ -840,6 +840,28 @@ function findTagEnd(html, pos, limit = html.length) {
840
840
  return -1;
841
841
  }
842
842
 
843
+ /**
844
+ * A package that resolves but fails to load—e.g., a native binding built for
845
+ * another platform—is not one another `npm install` fixes, so name what happened
846
+ * rather than the install command
847
+ *
848
+ * @param {string} label - Minifier name as it should read in the message
849
+ * @param {string} specifier - Package that failed to load
850
+ * @param {unknown} cause - Error the import rejected with
851
+ * @returns {string} Message describing the failure
852
+ */
853
+ function describeDependencyFailure(label, specifier, cause) {
854
+ const err = /** @type {any} */ (cause);
855
+ const notInstalled =
856
+ err?.code === 'ERR_MODULE_NOT_FOUND' && String(err?.message).includes(`'${specifier}'`);
857
+ if (notInstalled) {
858
+ return `The ${label} minifier requires ${specifier} to be installed.\n` +
859
+ `Install it with: npm install ${specifier}`;
860
+ }
861
+ return `The ${label} minifier could not load ${specifier}: ` +
862
+ (cause instanceof Error ? cause.message : String(cause));
863
+ }
864
+
843
865
  // Exports
844
866
 
845
867
  export {
@@ -857,5 +879,6 @@ export {
857
879
  parseRegExp,
858
880
  embedSource,
859
881
  lostFlag,
860
- describeQuantifierRisk
882
+ describeQuantifierRisk,
883
+ describeDependencyFailure
861
884
  };
@@ -3,8 +3,6 @@
3
3
  */
4
4
 
5
5
  import {
6
- RE_WS_START,
7
- RE_WS_END,
8
6
  RE_ALL_WS_NBSP,
9
7
  RE_NBSP_LEADING_GROUP,
10
8
  RE_NBSP_LEAD_GROUP,
@@ -15,37 +13,64 @@ import {
15
13
  formControlElements
16
14
  } from './constants.js';
17
15
 
16
+ const RE_ANY_WS_NBSP = /[ \n\r\t\f\xA0]/;
17
+ const RE_TAB_NBSP = /[\t\xA0]/;
18
+ const RE_ASCII_WS_RUN = /[ \n\r\f]+/g;
19
+ const RE_NEEDS_COLLAPSE = /[\n\r\f]| {2}/;
20
+ const RE_NON_WS = /\S/;
21
+
18
22
  // Trim whitespace
19
23
 
20
24
  /** @param {string} str */
21
25
  const trimWhitespace = str => {
22
26
  if (!str) return str;
23
- // Fast path: If no whitespace at start or end, return early
24
- if (!/^[ \n\r\t\f]/.test(str) && !/[ \n\r\t\f]$/.test(str)) {
25
- return str;
26
- }
27
- return str.replace(RE_WS_START, '').replace(RE_WS_END, '');
27
+ let start = 0;
28
+ let end = str.length;
29
+ while (start < end && isAsciiWs(str.charCodeAt(start))) start++;
30
+ while (end > start && isAsciiWs(str.charCodeAt(end - 1))) end--;
31
+ return start === 0 && end === str.length ? str : str.slice(start, end);
28
32
  };
29
33
 
34
+ /** @param {number} code */
35
+ function isAsciiWs(code) {
36
+ return code === 32 || code === 10 || code === 13 || code === 9 || code === 12;
37
+ }
38
+
39
+ /** @param {number} code */
40
+ function isWsOrNbsp(code) {
41
+ return code === 32 || code === 10 || code === 13 || code === 9 || code === 12 || code === 160;
42
+ }
43
+
30
44
  // Collapse all whitespace
31
45
 
46
+ // Module scope so the hot path doesn’t allocate a closure per call
47
+ /** @param {string} spaces */
48
+ function collapseRun(spaces) {
49
+ // Preserve standalone tabs
50
+ if (spaces === '\t') return '\t';
51
+ if (spaces.indexOf('\xA0') === -1) return ' ';
52
+ return spaces.replace(RE_NBSP_LEADING_GROUP, '$1 ');
53
+ }
54
+
32
55
  /** @param {string} str */
33
56
  function collapseWhitespaceAll(str) {
34
57
  if (!str) return str;
35
58
  // Fast path: If there are no common whitespace characters, return early
36
- if (!/[ \n\r\t\f\xA0]/.test(str)) {
59
+ if (!RE_ANY_WS_NBSP.test(str)) {
37
60
  return str;
38
61
  }
39
- // No-break space is specifically handled inside the replacer function here:
40
- return str.replace(RE_ALL_WS_NBSP, function (/** @param {string} spaces */ spaces) {
41
- // Preserve standalone tabs
42
- if (spaces === '\t') return '\t';
43
- // Fast path: No no-break space, common case—just collapse to single space
44
- // This avoids the nested regex for the majority of cases
45
- if (spaces.indexOf('\xA0') === -1) return ' ';
46
- // For no-break space handling, use the nested regex
47
- return spaces.replace(RE_NBSP_LEADING_GROUP, '$1 ');
48
- });
62
+ return collapseWhitespaceAllKnown(str);
63
+ }
64
+
65
+ // As `collapseWhitespaceAll`, for callers that already know `str` holds whitespace
66
+ /** @param {string} str */
67
+ function collapseWhitespaceAllKnown(str) {
68
+ // Only a tab or a no-break space makes the replacement depend on the run itself;
69
+ // without either, every run becomes one space and no per-match callback is needed
70
+ if (!RE_TAB_NBSP.test(str)) {
71
+ return RE_NEEDS_COLLAPSE.test(str) ? str.replace(RE_ASCII_WS_RUN, ' ') : str;
72
+ }
73
+ return str.replace(RE_ALL_WS_NBSP, collapseRun);
49
74
  }
50
75
 
51
76
  // Collapse whitespace with options
@@ -58,8 +83,6 @@ function collapseWhitespaceAll(str) {
58
83
  * @param {boolean} [collapseAll]
59
84
  */
60
85
  function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = false) {
61
- let lineBreakBefore = ''; let lineBreakAfter = '';
62
-
63
86
  if (!str) return str;
64
87
 
65
88
  // Fast path: Nothing to do
@@ -68,16 +91,30 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = fal
68
91
  }
69
92
 
70
93
  // Fast path: No whitespace at all
71
- if (!/[ \n\r\t\f\xA0]/.test(str)) {
94
+ if (!RE_ANY_WS_NBSP.test(str)) {
72
95
  return str;
73
96
  }
74
97
 
98
+ return collapseWhitespaceKnown(str, options, trimLeft, trimRight, collapseAll);
99
+ }
100
+
101
+ // As `collapseWhitespace`, for callers that already know `str` is non-empty, holds
102
+ // whitespace, and has something to do
103
+ /**
104
+ * @param {string} str
105
+ * @param {{preserveLineBreaks?: boolean | undefined, conservativeCollapse?: boolean | undefined}} options
106
+ * @param {boolean} trimLeft
107
+ * @param {boolean} trimRight
108
+ * @param {boolean} collapseAll
109
+ */
110
+ function collapseWhitespaceKnown(str, options, trimLeft, trimRight, collapseAll) {
111
+ let lineBreakBefore = ''; let lineBreakAfter = '';
112
+
75
113
  if (options.preserveLineBreaks) {
76
114
  // Find leading/trailing whitespace containing line breaks manually
77
115
  // (avoids polynomial backtracking with end-anchored lazy quantifiers)
78
- const WS_CHARS = ' \n\r\t\f';
79
116
  let leadEnd = 0;
80
- while (leadEnd < str.length && WS_CHARS.includes(str.charAt(leadEnd))) {
117
+ while (leadEnd < str.length && isAsciiWs(str.charCodeAt(leadEnd))) {
81
118
  leadEnd++;
82
119
  }
83
120
  if (leadEnd > 0) {
@@ -88,7 +125,7 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = fal
88
125
  }
89
126
  }
90
127
  let trailStart = str.length;
91
- while (trailStart > 0 && WS_CHARS.includes(str.charAt(trailStart - 1))) {
128
+ while (trailStart > 0 && isAsciiWs(str.charCodeAt(trailStart - 1))) {
92
129
  trailStart--;
93
130
  }
94
131
  if (trailStart < str.length) {
@@ -101,21 +138,34 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = fal
101
138
  }
102
139
 
103
140
  if (trimLeft) {
104
- // No-break space is specifically handled inside the replacer function
105
- str = str.replace(/^[ \n\r\t\f\xA0]+/, function (/** @type {string} */ spaces) {
141
+ // Find the leading whitespace boundary with a loop, so the common case neither
142
+ // allocates a replacer closure nor runs the regex machinery
143
+ let start = 0;
144
+ while (start < str.length && isWsOrNbsp(str.charCodeAt(start))) {
145
+ start++;
146
+ }
147
+ if (start > 0) {
148
+ const spaces = str.slice(0, start);
106
149
  const conservative = !lineBreakBefore && options.conservativeCollapse;
150
+ let replacement;
107
151
  if (conservative && spaces === '\t') {
108
- return '\t';
152
+ replacement = '\t';
153
+ } else if (spaces.indexOf('\xA0') === -1) {
154
+ // No no-break space: The whole run goes
155
+ replacement = conservative ? ' ' : '';
156
+ } else {
157
+ // No-break space is specifically handled via the nested regexes
158
+ replacement = spaces.replace(/^[^\xA0]+/, '').replace(RE_NBSP_LEAD_GROUP, '$1 ') || (conservative ? ' ' : '');
109
159
  }
110
- return spaces.replace(/^[^\xA0]+/, '').replace(RE_NBSP_LEAD_GROUP, '$1 ') || (conservative ? ' ' : '');
111
- });
160
+ str = replacement + str.slice(start);
161
+ }
112
162
  }
113
163
 
114
164
  if (trimRight) {
115
165
  // Find trailing whitespace boundary manually (avoids polynomial backtracking
116
166
  // with `/[ \n\r\t\f\xA0]+$/` on strings with long internal whitespace runs)
117
167
  let end = str.length;
118
- while (end > 0 && ' \n\r\t\f\xA0'.includes(str.charAt(end - 1))) {
168
+ while (end > 0 && isWsOrNbsp(str.charCodeAt(end - 1))) {
119
169
  end--;
120
170
  }
121
171
  if (end < str.length) {
@@ -124,6 +174,9 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = fal
124
174
  let replacement;
125
175
  if (conservative && spaces === '\t') {
126
176
  replacement = '\t';
177
+ } else if (spaces.indexOf('\xA0') === -1) {
178
+ // No no-break space: The whole run goes
179
+ replacement = conservative ? ' ' : '';
127
180
  } else {
128
181
  // No-break space is specifically handled via the nested regexes
129
182
  replacement = spaces.replace(RE_NBSP_TRAILING_GROUP, ' $1').replace(RE_NBSP_TRAILING_STRIP, '') || (conservative ? ' ' : '');
@@ -132,9 +185,9 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = fal
132
185
  }
133
186
  }
134
187
 
135
- if (collapseAll) {
188
+ if (collapseAll && str) {
136
189
  // Strip non-space whitespace then compress spaces to one
137
- str = collapseWhitespaceAll(str);
190
+ str = collapseWhitespaceAllKnown(str);
138
191
  }
139
192
 
140
193
  // Avoid string concatenation when no line breaks (common case)
@@ -149,11 +202,10 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll = fal
149
202
  // Check if an input element has `type="hidden"`; module-scope so the hot path
150
203
  // doesn’t allocate a closure per text node
151
204
  /**
152
- * @param {string} tagName
153
205
  * @param {Array<{name: string, value?: string}>} attrs
154
206
  */
155
- function isHiddenInput(tagName, attrs) {
156
- if (tagName !== 'input' || !attrs || !attrs.length) return false;
207
+ function isHiddenInput(attrs) {
208
+ if (!attrs || !attrs.length) return false;
157
209
  for (const attr of attrs) {
158
210
  if (attr.name === 'type') {
159
211
  return attr.value === 'hidden';
@@ -177,77 +229,67 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
177
229
 
178
230
  // Fast path: No whitespace at all—every decision below would leave `str`
179
231
  // untouched (`collapseWhitespace` returns such strings unchanged)
180
- if (!/[ \n\r\t\f\xA0]/.test(str)) {
232
+ if (!RE_ANY_WS_NBSP.test(str)) {
181
233
  return str;
182
234
  }
183
235
 
184
- const prevTagName = prevTag && (prevTag.charAt(0) === '/' ? prevTag.slice(1) : prevTag);
185
- const nextTagName = nextTag && (nextTag.charAt(0) === '/' ? nextTag.slice(1) : nextTag);
186
-
187
- // Check if prev/next are non-rendering (hidden) elements
188
- const prevIsHidden = isHiddenInput(prevTagName, prevAttrs);
189
- const nextIsHidden = isHiddenInput(nextTagName, nextAttrs);
190
-
191
- let trimLeft = prevTag && !inlineElementsToKeepWhitespace.has(prevTag);
192
-
193
- // Whether the text is whitespace only—one scan, shared by the checks below
194
- // (`str` is known non-empty here)
195
- const isPureWhitespace = !/\S/.test(str);
236
+ const inlineOption = Boolean(options.collapseInlineTagWhitespace);
196
237
 
197
- // Smart default behavior: Collapse space after non-rendering elements (`type="hidden"`)
198
- // This happens even in basic `collapseWhitespace` mode (safe optimization)
199
- if (!trimLeft && prevIsHidden && isPureWhitespace) {
200
- trimLeft = true;
201
- }
202
-
203
- // Aggressive mode: Collapse between all form controls (pure whitespace only)
204
- if (!trimLeft && prevTagName && nextTagName &&
205
- options.collapseInlineTagWhitespace &&
206
- isPureWhitespace &&
207
- formControlElements.has(prevTagName) && formControlElements.has(nextTagName)) {
208
- trimLeft = true;
209
- }
238
+ let trimLeft = Boolean(prevTag) && !inlineElementsToKeepWhitespace.has(prevTag);
239
+ let trimRight = Boolean(nextTag) && !inlineElementsToKeepWhitespace.has(nextTag);
210
240
 
211
- if (trimLeft && !options.collapseInlineTagWhitespace) {
212
- trimLeft = prevTag.charAt(0) === '/' ? !inlineElements.has(prevTag.slice(1)) : !inlineTextSet.has(prevTag);
213
- }
241
+ // Every branch below that consults the text’s content needs a side left untrimmed,
242
+ // so the scan for a non-whitespace character is only worth making then
243
+ const isPureWhitespace = (!trimLeft || !trimRight) && !RE_NON_WS.test(str);
214
244
 
215
- // When `collapseInlineTagWhitespace` is enabled, still preserve whitespace around inline text elements
216
- if (trimLeft && options.collapseInlineTagWhitespace) {
217
- const tagName = prevTag.charAt(0) === '/' ? prevTag.slice(1) : prevTag;
218
- if (inlineElementsToKeepWhitespaceWithin.has(tagName)) {
219
- trimLeft = false;
245
+ if (isPureWhitespace) {
246
+ // Smart default behavior: Collapse space around non-rendering elements
247
+ // (`type="hidden"`); this happens even in basic `collapseWhitespace` mode
248
+ if (!trimLeft && prevTag === 'input' && isHiddenInput(prevAttrs)) {
249
+ trimLeft = true;
250
+ }
251
+ if (!trimRight && nextTag === 'input' && isHiddenInput(nextAttrs)) {
252
+ trimRight = true;
253
+ }
254
+ // Aggressive mode: Collapse between all form controls
255
+ if (inlineOption && (!trimLeft || !trimRight) &&
256
+ formControlElements.has(stripSlash(prevTag)) && formControlElements.has(stripSlash(nextTag))) {
257
+ trimLeft = true;
258
+ trimRight = true;
220
259
  }
221
260
  }
222
261
 
223
- let trimRight = nextTag && !inlineElementsToKeepWhitespace.has(nextTag);
224
-
225
- // Smart default behavior: Collapse space before non-rendering elements (`type="hidden"`)
226
- if (!trimRight && nextIsHidden && isPureWhitespace) {
227
- trimRight = true;
228
- }
229
-
230
- // Aggressive mode: Same as `trimLeft`
231
- if (!trimRight && prevTagName && nextTagName &&
232
- options.collapseInlineTagWhitespace &&
233
- isPureWhitespace &&
234
- formControlElements.has(prevTagName) && formControlElements.has(nextTagName)) {
235
- trimRight = true;
262
+ if (trimLeft) {
263
+ if (inlineOption) {
264
+ // Still preserve whitespace around inline text elements
265
+ if (inlineElementsToKeepWhitespaceWithin.has(stripSlash(prevTag))) {
266
+ trimLeft = false;
267
+ }
268
+ } else {
269
+ trimLeft = prevTag.charCodeAt(0) === 47 /* / */ ? !inlineElements.has(prevTag.slice(1)) : !inlineTextSet.has(prevTag);
270
+ }
236
271
  }
237
272
 
238
- if (trimRight && !options.collapseInlineTagWhitespace) {
239
- trimRight = nextTag.charAt(0) === '/' ? !inlineTextSet.has(nextTag.slice(1)) : !inlineElements.has(nextTag);
273
+ if (trimRight) {
274
+ if (inlineOption) {
275
+ if (inlineElementsToKeepWhitespaceWithin.has(stripSlash(nextTag))) {
276
+ trimRight = false;
277
+ }
278
+ } else {
279
+ trimRight = nextTag.charCodeAt(0) === 47 /* / */ ? !inlineTextSet.has(nextTag.slice(1)) : !inlineElements.has(nextTag);
280
+ }
240
281
  }
241
282
 
242
- // When `collapseInlineTagWhitespace` is enabled, still preserve whitespace around inline text elements
243
- if (trimRight && options.collapseInlineTagWhitespace) {
244
- const tagName = nextTag.charAt(0) === '/' ? nextTag.slice(1) : nextTag;
245
- if (inlineElementsToKeepWhitespaceWithin.has(tagName)) {
246
- trimRight = false;
247
- }
283
+ const collapseAll = Boolean(prevTag && nextTag);
284
+ if (!trimLeft && !trimRight && !collapseAll && !options.preserveLineBreaks) {
285
+ return str;
248
286
  }
287
+ return collapseWhitespaceKnown(str, options, trimLeft, trimRight, collapseAll);
288
+ }
249
289
 
250
- return collapseWhitespace(str, options, Boolean(trimLeft), Boolean(trimRight), Boolean(prevTag && nextTag));
290
+ /** @param {string} tag */
291
+ function stripSlash(tag) {
292
+ return tag && tag.charCodeAt(0) === 47 /* / */ ? tag.slice(1) : tag;
251
293
  }
252
294
 
253
295
  // Collapse/trim whitespace for given tag