html-minifier-next 8.1.0 → 8.1.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.
@@ -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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AAcG,YAWG,iBAAiB,GAXV;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,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CACxC,CAAmB;AAyCvB,eAAO,MAAM,MAAM,QAA8C,CAAC;AA2HlE,qBAAa,UAAU;IAMd,IAAI;IACJ,OAAO;IANd;;;OAGG;IACH,YAAY,IAAI,EAHL,MAGK,EAAE,OAAO,EAFd,iBAEc,EAGxB;IAEK,KAAK,kBAypBV;CACF"}
1
+ {"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AAeG,YAWG,iBAAiB,GAXV;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,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;AAoJlE,qBAAa,UAAU;IAMd,IAAI;IACJ,OAAO;IANd;;;OAGG;IACH,YAAY,IAAI,EAHL,MAGK,EAAE,OAAO,EAFd,iBAEc,EAGxB;IAEK,KAAK,kBAouBV;CACF"}
@@ -1,5 +1,7 @@
1
1
  declare const RE_WS_START: RegExp;
2
2
  declare const RE_WS_END: RegExp;
3
+ declare const RE_WS_ONLY: RegExp;
4
+ declare const RE_WS_NBSP_END: RegExp;
3
5
  declare const RE_ALL_WS_NBSP: RegExp;
4
6
  declare const RE_NBSP_LEADING_GROUP: RegExp;
5
7
  declare const RE_NBSP_LEAD_GROUP: RegExp;
@@ -11,6 +13,8 @@ declare const RE_TRAILING_SEMICOLON: RegExp;
11
13
  declare const RE_AMP_ENTITY: RegExp;
12
14
  declare const RE_LEGACY_ENTITIES: RegExp;
13
15
  declare const RE_ESCAPE_LT: RegExp;
16
+ declare const RE_ESCAPE_LT_RAW_TEXT: Record<string, RegExp>;
17
+ declare const RE_HTML_ENCODING: RegExp;
14
18
  declare const RE_ATTR_WS_CHECK: RegExp;
15
19
  declare const RE_ATTR_WS_COLLAPSE: RegExp;
16
20
  declare const RE_ATTR_WS_TRIM: RegExp;
@@ -95,5 +99,8 @@ declare const looseElements: Set<string>;
95
99
  declare const trailingElements: Set<string>;
96
100
  declare const htmlElements: Set<string>;
97
101
  declare const specialContentElements: Set<string>;
98
- export { RE_WS_START, RE_WS_END, RE_ALL_WS_NBSP, RE_NBSP_LEADING_GROUP, RE_NBSP_LEAD_GROUP, RE_NBSP_TRAILING_GROUP, RE_NBSP_TRAILING_STRIP, RE_EVENT_ATTR_DEFAULT, RE_CAN_REMOVE_ATTR_QUOTES, RE_TRAILING_SEMICOLON, RE_AMP_ENTITY, RE_LEGACY_ENTITIES, RE_ESCAPE_LT, RE_ATTR_WS_CHECK, RE_ATTR_WS_COLLAPSE, RE_ATTR_WS_TRIM, RE_STYLE_ELEMENT, 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 };
102
+ declare const genericRawTextElements: Set<string>;
103
+ declare const escapableRawTextElements: Set<string>;
104
+ declare const rawTextElements: Set<string>;
105
+ 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, escapableRawTextElements, rawTextElements };
99
106
  //# 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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"}
@@ -89,8 +89,9 @@ declare function describeQuantifierRisk(pattern: RegExp | string): string | null
89
89
  * over quoted attribute values (which may contain `>`).
90
90
  * @param {string} html
91
91
  * @param {number} pos - Start position (just after the tag name)
92
+ * @param {number} [limit] - Position to stop the search at (exclusive)
92
93
  * @returns {number} Index of the closing `>`, or -1 if not found
93
94
  */
94
- declare function findTagEnd(html: string, pos: number): number;
95
+ declare function findTagEnd(html: string, pos: number, limit?: number): number;
95
96
  export { stableStringify, findTagEnd, LRU, MAX_CACHE_ENTRY_SIZE, hashContent, uniqueId, identity, isThenable, lowercase, replaceAsync, parseRegExp, embedSource, lostFlag, describeQuantifierRisk };
96
97
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH,iBAAS,eAAe,CAAC,GAAG,EAHjB,OAGiB,GAFf,MAAM,CAYlB;AAID,cAAM,GAAG;IAEA,KAAK;IACL,IAAI;IACJ,IAAI;IACT,mCAAmC;IAC9B,GAAG,EADG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAJjC,YAAY,KAAK,SAAM,EAMtB;IACD,0BAA0B;IAC1B,GAAG,CAAC,GAAG,EADK,MACL,WAUN;IACD;;;OAGG;IACH,GAAG,CAAC,GAAG,EAHI,MAGJ,EAAE,KAAK,EAFH,OAEG,QAOb;IACD,0BAA0B;IAC1B,MAAM,CAAC,GAAG,EADE,MACF,QAA2B;IACrC,6EAA6E;IAC7E,KAAK,IADS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAGxE;CACF;AAKD,QAAA,MAAM,oBAAoB,QAAc,CAAC;AAIzC,0BAA0B;AAC1B,iBAAS,WAAW,CAAC,GAAG,EADZ,MACY,UAOvB;AAID,4BAA4B;AAC5B,iBAAS,QAAQ,CAAC,KAAK,EADX,MACW,UAMtB;AAID,4BAA4B;AAC5B,iBAAS,QAAQ,CAAC,KAAK,EADX,MACW,UAEtB;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,KAAK,EAHd,OAGc,GAFZ,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,CAIrC;AAED,4BAA4B;AAC5B,iBAAS,SAAS,CAAC,KAAK,EADZ,MACY,UAEvB;AAID;;;;;;GAMG;AACH,iBAAe,YAAY,CAAC,GAAG,EALpB,MAKoB,EAAE,KAAK,EAJ3B,MAI2B,EAAE,OAAO,UAAA,GAFlC,OAAO,CAAC,MAAM,CAAC,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;;;;;;GAMG;AACH,iBAAS,UAAU,CAAC,IAAI,EAJb,MAIa,EAAE,GAAG,EAHlB,MAGkB,GAFhB,MAAM,CAelB;AAID,OAAO,EACL,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,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":"AAEA;;;GAGG;AACH,iBAAS,eAAe,CAAC,GAAG,EAHjB,OAGiB,GAFf,MAAM,CAYlB;AAID,cAAM,GAAG;IAEA,KAAK;IACL,IAAI;IACJ,IAAI;IACT,mCAAmC;IAC9B,GAAG,EADG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAJjC,YAAY,KAAK,SAAM,EAMtB;IACD,0BAA0B;IAC1B,GAAG,CAAC,GAAG,EADK,MACL,WAUN;IACD;;;OAGG;IACH,GAAG,CAAC,GAAG,EAHI,MAGJ,EAAE,KAAK,EAFH,OAEG,QAOb;IACD,0BAA0B;IAC1B,MAAM,CAAC,GAAG,EADE,MACF,QAA2B;IACrC,6EAA6E;IAC7E,KAAK,IADS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAGxE;CACF;AAKD,QAAA,MAAM,oBAAoB,QAAc,CAAC;AAIzC,0BAA0B;AAC1B,iBAAS,WAAW,CAAC,GAAG,EADZ,MACY,UAOvB;AAID,4BAA4B;AAC5B,iBAAS,QAAQ,CAAC,KAAK,EADX,MACW,UAMtB;AAID,4BAA4B;AAC5B,iBAAS,QAAQ,CAAC,KAAK,EADX,MACW,UAEtB;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,KAAK,EAHd,OAGc,GAFZ,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,CAIrC;AAED,4BAA4B;AAC5B,iBAAS,SAAS,CAAC,KAAK,EADZ,MACY,UAEvB;AAID;;;;;;GAMG;AACH,iBAAe,YAAY,CAAC,GAAG,EALpB,MAKoB,EAAE,KAAK,EAJ3B,MAI2B,EAAE,OAAO,UAAA,GAFlC,OAAO,CAAC,MAAM,CAAC,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,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,sBAAsB,EACvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../../src/lib/whitespace.js"],"names":[],"mappings":"AAeA,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,UAiEnH;AAOD,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":"AAeA,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,UAiEnH;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"}
package/package.json CHANGED
@@ -16,9 +16,9 @@
16
16
  "devDependencies": {
17
17
  "@commitlint/cli": "^21.2.2",
18
18
  "@eslint/js": "^10.0.1",
19
- "@swc/core": "^1.16.0",
19
+ "@swc/core": "^1.16.1",
20
20
  "@types/node": "^26.2.0",
21
- "eslint": "^10.8.1",
21
+ "eslint": "^10.9.1",
22
22
  "globals": "^17.11.0",
23
23
  "typescript": "^7.0.2",
24
24
  "vite": "^8.2.1"
@@ -95,5 +95,5 @@
95
95
  },
96
96
  "type": "module",
97
97
  "types": "dist/types/htmlminifier.d.ts",
98
- "version": "8.1.0"
98
+ "version": "8.1.2"
99
99
  }
@@ -8,10 +8,17 @@ import { collectUsedSymbols } from './lib/unused-css.js';
8
8
  import {
9
9
  RE_LEGACY_ENTITIES,
10
10
  RE_ESCAPE_LT,
11
+ RE_ESCAPE_LT_RAW_TEXT,
12
+ RE_HTML_ENCODING,
13
+ RE_WS_START,
14
+ RE_WS_END,
15
+ RE_WS_ONLY,
16
+ RE_WS_NBSP_END,
11
17
  RE_STYLE_ELEMENT,
12
18
  inlineElementsToKeepWhitespaceAround,
13
19
  inlineElementsToKeepWhitespaceWithin,
14
20
  specialContentElements,
21
+ rawTextElements,
15
22
  htmlElements,
16
23
  optionalStartTags,
17
24
  optionalEndTags,
@@ -574,14 +581,14 @@ const DEFAULT_JS_TYPES = new Set(['', 'text/javascript', 'application/javascript
574
581
  // Pre-compiled patterns for buffer scanning
575
582
  const RE_START_TAG = /^<[^/!]/;
576
583
  const RE_END_TAG = /^<\//;
584
+ const RE_WHITESPACE_ONLY = /^\s+$/;
585
+ const RE_TRAILING_WHITESPACE = /\s$/;
577
586
 
578
587
  // Pre-compiled patterns for `htmlmin:ignore` block content analysis
579
588
  const RE_HTML_COMMENT_START = /^\s*<!--/;
580
589
  const RE_CLOSING_TAG_START = /^\s*<\/([a-zA-Z][\w:-]*)/;
581
590
  const RE_LAST_HTML_TAG = /[\s\S]*<(\/?[a-zA-Z][\w:-]*)/;
582
591
 
583
- // HTML encoding types for annotation-xml (MathML)
584
- const RE_HTML_ENCODING = /^(text\/html|application\/xhtml\+xml)$/i;
585
592
 
586
593
  // Probe for SVG/MathML elements—when the input has none (the common case),
587
594
  // the per-tag foreign-content machinery can be skipped entirely
@@ -1117,11 +1124,65 @@ async function minifyHTML(value, options, partialMarkup) {
1117
1124
  buffer.length = Math.max(0, index);
1118
1125
  }
1119
1126
 
1127
+ // Whether the element being parsed holds text rather than markup. The namespace decides
1128
+ // this, not the name alone: `script` and `style` hold text wherever they stand, the rest
1129
+ // only as HTML elements—an SVG or MathML `title` holds markup like any foreign element
1130
+ function holdsRawText() {
1131
+ return specialContentElements.has(currentTag) ||
1132
+ (rawTextElements.has(currentTag) && !options.insideForeignContent);
1133
+ }
1134
+
1135
+ // Whether whitespace-only text between tags survives minification
1136
+ function keepsWhitespace() {
1137
+ return !options.collapseWhitespace || Boolean(options.conservativeCollapse) || Boolean(options.preserveLineBreaks);
1138
+ }
1139
+
1140
+ // The two whitespace runs an omitted tag separated become one run, which collapses to the
1141
+ // single character it is due: a line break under `preserveLineBreaks`, a no-break space
1142
+ // where the run holds one, a space under `conservativeCollapse`
1143
+ function mergeWhitespaceRuns(/** @type {number} */ index) {
1144
+ let before = index - 1;
1145
+ while (before >= 0 && buffer[before] === '') {
1146
+ before--;
1147
+ }
1148
+ let after = index;
1149
+ while (after < buffer.length && buffer[after] === '') {
1150
+ after++;
1151
+ }
1152
+ if (before < 0 || after >= buffer.length) {
1153
+ return;
1154
+ }
1155
+ const prev = buffer[before] ?? '';
1156
+ const next = buffer[after] ?? '';
1157
+ if (!RE_WS_NBSP_END.test(prev) || !RE_WS_START.test(next)) {
1158
+ return;
1159
+ }
1160
+ // A line break the run already carries outranks the whitespace ahead of it; trimming
1161
+ // the other side takes ASCII whitespace only, so a no-break space stays as is
1162
+ if (options.preserveLineBreaks && /[\n\r]/.test((next.match(RE_WS_START) ?? [''])[0])) {
1163
+ buffer[before] = prev.replace(RE_WS_END, '');
1164
+ } else {
1165
+ buffer[after] = next.replace(RE_WS_START, '');
1166
+ }
1167
+ }
1168
+
1120
1169
  function removeEndTag() {
1121
1170
  let index = buffer.length - 1;
1122
1171
  while (index > 0 && !RE_END_TAG.test(buffer[index] ?? '')) {
1123
1172
  index--;
1124
1173
  }
1174
+ // Text that follows the end tag is kept as is, so drop the tag alone. Whitespace kept
1175
+ // verbatim—in `pre`, in `textarea`, or wherever `canTrimWhitespace` says so—counts as
1176
+ // kept text too, no matter how whitespace is collapsed elsewhere.
1177
+ const noTrim = stackNoTrimWhitespace.length > 0;
1178
+ if (index < buffer.length - 1 && (keepsWhitespace() || noTrim) && RE_END_TAG.test(buffer[index] ?? '')) {
1179
+ buffer.splice(index, 1);
1180
+ // Only collapsed whitespace can merge
1181
+ if (options.collapseWhitespace && !noTrim) {
1182
+ mergeWhitespaceRuns(index);
1183
+ }
1184
+ return;
1185
+ }
1125
1186
  buffer.length = Math.max(0, index);
1126
1187
  }
1127
1188
 
@@ -1143,11 +1204,15 @@ async function minifyHTML(value, options, partialMarkup) {
1143
1204
  // element which has now been removed
1144
1205
  function squashTrailingWhitespace(/** @type {string} */ nextTag) {
1145
1206
  let charsIndex = buffer.length - 1;
1146
- if (buffer.length > 1) {
1147
- const item = buffer[buffer.length - 1] ?? '';
1148
- if (/^(?:<!|$)/.test(item) && (!uidIgnore || item.indexOf(uidIgnore) === -1)) {
1149
- charsIndex--;
1207
+ // Step back over every trailing comment and empty entry, not just one—a single step
1208
+ // stops the search at the comment itself, leaving whitespace behind that a second
1209
+ // minification run then removes
1210
+ while (charsIndex > 0) {
1211
+ const item = buffer[charsIndex] ?? '';
1212
+ if (!/^(?:<!|$)/.test(item) || (uidIgnore && item.indexOf(uidIgnore) !== -1)) {
1213
+ break;
1150
1214
  }
1215
+ charsIndex--;
1151
1216
  }
1152
1217
  trimTrailingWhitespace(charsIndex, nextTag);
1153
1218
  }
@@ -1240,7 +1305,7 @@ async function minifyHTML(value, options, partialMarkup) {
1240
1305
  } else {
1241
1306
  text = collapseWhitespace(text, options, true, true);
1242
1307
  }
1243
- if (!text && /\s$/.test(currentChars) && textPrevTag && textPrevTag.charAt(0) === '/') {
1308
+ if (!text && RE_TRAILING_WHITESPACE.test(currentChars) && textPrevTag && textPrevTag.charAt(0) === '/') {
1244
1309
  trimTrailingWhitespace(buffer.length - 1, textNextTag);
1245
1310
  }
1246
1311
  }
@@ -1277,15 +1342,22 @@ async function minifyHTML(value, options, partialMarkup) {
1277
1342
  // `</head>`, `</colgroup>`, or `</caption>` may be omitted if not followed by space or comment
1278
1343
  if (optionalEndTagEmitted && (compactElements.has(optionalEndTag) || (looseElements.has(optionalEndTag) && !/^\s/.test(effectiveText)))) {
1279
1344
  removeEndTag();
1345
+ // The tag is gone from the buffer, so nothing is left to omit later
1346
+ optionalEndTag = '';
1347
+ optionalEndTagEmitted = false;
1280
1348
  }
1281
- // Don’t reset `optionalEndTag` if text is only whitespace and will be collapsed (not conservatively)
1282
- if (!/^\s+$/.test(text) || !options.collapseWhitespace || options.conservativeCollapse) {
1349
+ // Whitespace-only text doesn’t prevent omission of the pending end tag: It’s either
1350
+ // collapsed away, or kept in place while the tag alone is dropped—except for
1351
+ // `</head>`, `</colgroup>`, and `</caption>`, which may not be followed by space.
1352
+ // Only ASCII whitespace counts, as no-break space and friends are content
1353
+ // https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
1354
+ if (!RE_WS_ONLY.test(text) || (keepsWhitespace() && looseElements.has(optionalEndTag))) {
1283
1355
  optionalEndTag = '';
1284
1356
  optionalEndTagEmitted = false;
1285
1357
  }
1286
1358
  }
1287
1359
  charsPrevTag = /^\s*$/.test(text) ? textPrevTag : 'comment';
1288
- if (options.decodeEntities && text && !specialContentElements.has(currentTag)) {
1360
+ if (options.decodeEntities && text && !holdsRawText()) {
1289
1361
  // Escape any `&` symbols that start either:
1290
1362
  // 1. a legacy-named character reference (i.e., one that doesn’t end with `;`)
1291
1363
  // 2. or any other character reference (i.e., one that does end with `;`)
@@ -1295,7 +1367,10 @@ async function minifyHTML(value, options, partialMarkup) {
1295
1367
  text = text.replace(RE_LEGACY_ENTITIES, '&amp$1');
1296
1368
  }
1297
1369
  if (text.indexOf('<') !== -1) {
1298
- text = text.replace(RE_ESCAPE_LT, '&lt;');
1370
+ // Escapable raw text ends at its own end tag alone, so only that one needs escaping;
1371
+ // in foreign content the same element holds markup, where every `<` does
1372
+ const escapeLt = (options.insideForeignContent ? undefined : RE_ESCAPE_LT_RAW_TEXT[currentTag]) ?? RE_ESCAPE_LT;
1373
+ text = text.replace(escapeLt, '&lt;');
1299
1374
  }
1300
1375
  }
1301
1376
  if (uidPattern && options.collapseWhitespace && stackNoTrimWhitespace.length) {
@@ -1347,7 +1422,7 @@ async function minifyHTML(value, options, partialMarkup) {
1347
1422
  const prevComment = buffer[buffer.length - 2];
1348
1423
 
1349
1424
  // Check if previous item is whitespace-only and item before that is ignore-placeholder
1350
- if (prevText && /^\s+$/.test(prevText) && prevComment && uidIgnorePlaceholderPattern.test(prevComment)) {
1425
+ if (prevText && RE_WHITESPACE_ONLY.test(prevText) && prevComment && uidIgnorePlaceholderPattern.test(prevComment)) {
1351
1426
  // Extract the index from both placeholders to check their content
1352
1427
  const currentMatch = comment.match(uidIgnorePlaceholderPattern);
1353
1428
  const prevMatch = prevComment.match(uidIgnorePlaceholderPattern);
@@ -1390,7 +1465,11 @@ async function minifyHTML(value, options, partialMarkup) {
1390
1465
  // Apply `collapseWhitespace` with appropriate context
1391
1466
  if (!stackNoTrimWhitespace.length && !stackNoCollapseWhitespace.length) {
1392
1467
  // Not in pre or other no-collapse context
1393
- if (options.preserveLineBreaks && /[\n\r]/.test(prevText)) {
1468
+ if (prevText.includes('\xA0')) {
1469
+ // No-break spaces are content, so every one of them survives in place;
1470
+ // the ASCII whitespace around them collapses as it would anywhere else
1471
+ collapsedText = collapseWhitespace(prevText, options, true, true, true);
1472
+ } else if (options.preserveLineBreaks && /[\n\r]/.test(prevText)) {
1394
1473
  // Preserve line break as single newline
1395
1474
  collapsedText = '\n';
1396
1475
  } else if (options.conservativeCollapse) {
@@ -1464,10 +1543,11 @@ async function minifyHTML(value, options, partialMarkup) {
1464
1543
  options.removeTagWhitespace = false;
1465
1544
  }
1466
1545
  // `foreignObject` in SVG and `annotation-xml` in MathML contain HTML content
1467
- // Note: The element itself is in SVG/MathML namespace, only its children are HTML
1546
+ // (the element itself is in SVG/MathML namespace, only its children are HTML);
1547
+ // a repeated attribute is dropped after the first, so the first `encoding` decides
1468
1548
  if (options.insideForeignContent && (lowerTag === 'foreignobject' ||
1469
- (lowerTag === 'annotation-xml' && attrs.some((/** @type {HTMLAttribute} */ a) => a.name.toLowerCase() === 'encoding' &&
1470
- RE_HTML_ENCODING.test(a.value ?? ''))))) {
1549
+ (lowerTag === 'annotation-xml' && RE_HTML_ENCODING.test(
1550
+ attrs.find((/** @type {HTMLAttribute} */ a) => a.name.toLowerCase() === 'encoding')?.value ?? '')))) {
1471
1551
  const nameParent = options.name;
1472
1552
  options = Object.create(options);
1473
1553
  options.caseSensitive = false;
@@ -1639,10 +1719,11 @@ async function minifyHTML(value, options, partialMarkup) {
1639
1719
  removeStartTag();
1640
1720
  }
1641
1721
  optionalStartTag = '';
1642
- // `</html>` or `</body>` may be omitted if not followed by comment
1643
- // `</head>` may be omitted if not followed by space or comment
1644
- // `</p>` may be omitted if no more content in parent, unless parent is in `pInlineElements` or is a custom element
1645
- // https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
1722
+ // `</html>` or `</body>` may be omitted if not followed by comment,
1723
+ // `</head>` may be omitted if not followed by space or comment,
1724
+ // `</p>` may be omitted if no more content in parent,
1725
+ // unless parent is in `pInlineElements` or is a custom element
1726
+ // (https://html.spec.whatwg.org/multipage/syntax.html#optional-tags);
1646
1727
  // except for `</dt>` or `</thead>`, end tags may be omitted if no more content in parent element
1647
1728
  if (tag && optionalEndTag && optionalEndTagEmitted && !trailingElements.has(optionalEndTag) && (optionalEndTag !== 'p' || (!pInlineElements.has(tag) && !tag.includes('-')))) {
1648
1729
  removeEndTag();
@@ -1710,7 +1791,7 @@ async function minifyHTML(value, options, partialMarkup) {
1710
1791
  textNextAttrs = nextAttrs || [];
1711
1792
 
1712
1793
  // Detect whether any async work is actually needed for this text node
1713
- const needsDecode = options.decodeEntities && text && !specialContentElements.has(currentTag) && text.indexOf('&') !== -1;
1794
+ const needsDecode = options.decodeEntities && text && !holdsRawText() && text.indexOf('&') !== -1;
1714
1795
  const needsProcessScript = specialContentElements.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs));
1715
1796
  const needsMinifyJS = options.minifyJS !== identity && isExecutableScript(currentTag, currentAttrs);
1716
1797
  const isModuleScript = needsMinifyJS && currentAttrs.some(
package/src/htmlparser.js CHANGED
@@ -5,7 +5,8 @@
5
5
  * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
6
6
  */
7
7
 
8
- import { isThenable, embedSource } from './lib/utils.js';
8
+ import { isThenable, embedSource, findTagEnd } from './lib/utils.js';
9
+ import { escapableRawTextElements, genericRawTextElements, RE_HTML_ENCODING } from './lib/constants.js';
9
10
 
10
11
  /** @import { HTMLAttribute } from './lib/attributes.js' */
11
12
 
@@ -64,6 +65,7 @@ const qnameCapture = (function () {
64
65
  return '((?:' + ncname + '\\:)?' + ncname + ')';
65
66
  })();
66
67
  const startTagOpen = new RegExp('^<' + qnameCapture);
68
+ const endTagOpen = new RegExp('^</' + qnameCapture);
67
69
  export const endTag = new RegExp('^</' + qnameCapture + '[^>]*>');
68
70
 
69
71
  let IS_REGEX_CAPTURING_BROKEN = false;
@@ -84,45 +86,70 @@ const fillAttrs = new Set(['checked', 'compact', 'declare', 'defer', 'disabled',
84
86
  // Special elements (can contain anything)
85
87
  const special = new Set(['script', 'style']);
86
88
 
89
+ // Elements whose children are HTML rather than foreign content, each only in
90
+ // the namespace it belongs to (`annotation-xml` is one, too, but only for some
91
+ // `encoding` values, so it is checked separately)
92
+ // https://html.spec.whatwg.org/multipage/parsing.html#html-integration-point
93
+ const svgIntegrationPoints = new Set(['foreignobject', 'desc', 'title']);
94
+ const mathIntegrationPoints = new Set(['mi', 'mo', 'mn', 'ms', 'mtext']);
95
+
87
96
  // HTML elements, https://html.spec.whatwg.org/multipage/indices.html#elements-3
88
97
  // Phrasing content, https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
89
- const nonPhrasing = new Set(['address', 'article', 'aside', 'base', 'blockquote', 'body', 'caption', 'col', 'colgroup', 'dd', 'details', 'dialog', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'legend', 'li', 'menuitem', 'meta', 'ol', 'optgroup', 'option', 'param', 'rp', 'rt', 'source', 'style', 'summary', 'tbody', 'td', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul']);
90
-
91
- const reCache = {};
98
+ const nonPhrasing = new Set(['address', 'article', 'aside', 'base', 'blockquote', 'body', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dialog', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'legend', 'li', 'listing', 'main', 'menu', 'menuitem', 'meta', 'nav', 'ol', 'optgroup', 'option', 'param', 'plaintext', 'pre', 'rp', 'rt', 'search', 'section', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'xmp']);
92
99
 
93
- // Pre-compiled regexes for common special elements (`script`, `style`, `noscript`)
94
- // These are used frequently, and pre-compiling them avoids regex creation overhead
95
- const preCompiledStackedTags = {
96
- 'script': /([\s\S]*?)<\/script[^>]*>/i,
97
- 'style': /([\s\S]*?)<\/style[^>]*>/i,
98
- 'noscript': /([\s\S]*?)<\/noscript[^>]*>/i
99
- };
100
+ // A tag name ends at whitespace, a slash, or the closing bracket, so `</scriptx>` names a
101
+ // different element and does not end this one
102
+ const endsTagName = (/** @type {string} */ character) =>
103
+ character === '' || character === '/' || character === '>' || /\s/.test(character);
100
104
 
101
- // Cache for compiled attribute regexes per handler configuration
102
- const attrRegexCache = new WeakMap();
105
+ /**
106
+ * @param {string} text - The input the tag stands in
107
+ * @param {number} nameEnd - Position right after the tag name
108
+ * @returns {number} Position of the `>` that ends the tag, or -1 where none follows
109
+ */
110
+ function findEndTagClose(text, nameEnd) {
111
+ const close = text.indexOf('>', nameEnd);
112
+ if (close === -1) {
113
+ return -1;
114
+ }
115
+ // A quoted attribute value can hold a `>` that does not end the tag it stands in, so a
116
+ // quote ahead of that bracket calls for a scan that knows about quoting. It stops at the
117
+ // next `<`, which no tag reaches past: The scans of consecutive tags then never overlap,
118
+ // and an unquoted value that spans one leaves the first bracket as the end, as before.
119
+ for (let index = nameEnd; index < close; index++) {
120
+ const character = text[index];
121
+ if (character === '"' || character === "'") {
122
+ const nextOpen = text.indexOf('<', nameEnd);
123
+ const quoted = findTagEnd(text, nameEnd, nextOpen === -1 ? text.length : nextOpen);
124
+ return quoted === -1 ? close : quoted;
125
+ }
126
+ }
127
+ return close;
128
+ }
103
129
 
104
- // O(n) helper: Strip all occurrences of `open…close` delimiters, keeping inner content
105
- // Used instead of a regex replace to avoid O(n²) behavior on adversarial inputs
106
130
  /**
107
- * @param {string} str
108
- * @param {string} open
109
- * @param {string} close
131
+ * @param {string} text - The input from the start of the content on
132
+ * @param {string} tag - Lowercase element name
133
+ * @returns {{content: string, length: number} | null} What the element holds and how far it
134
+ * reaches, or `null` where no end tag of its own follows
110
135
  */
111
- function stripDelimited(str, open, close) {
112
- let result = '';
113
- let i = 0;
114
- while (i < str.length) {
115
- const start = str.indexOf(open, i);
116
- if (start === -1) { result += str.slice(i); break; }
117
- result += str.slice(i, start);
118
- const end = str.indexOf(close, start + open.length);
119
- if (end === -1) { result += str.slice(start); break; }
120
- result += str.slice(start + open.length, end);
121
- i = end + close.length;
136
+ function findRawTextEnd(text, tag) {
137
+ const nameEnd = tag.length + 2;
138
+ for (let candidate = text.indexOf('</'); candidate !== -1; candidate = text.indexOf('</', candidate + 2)) {
139
+ if (text.slice(candidate + 2, candidate + nameEnd).toLowerCase() !== tag || !endsTagName(text.charAt(candidate + nameEnd))) {
140
+ continue;
141
+ }
142
+ // What follows the name is not part of it, and the tag ends at the next bracket outside
143
+ // its attribute values—where none follows, no later end tag can be complete, either
144
+ const end = findEndTagClose(text, candidate + nameEnd);
145
+ return end === -1 ? null : { content: text.slice(0, candidate), length: end + 1 };
122
146
  }
123
- return result;
147
+ return null;
124
148
  }
125
149
 
150
+ // Cache for compiled attribute regexes per handler configuration
151
+ const attrRegexCache = new WeakMap();
152
+
126
153
  /** @param {HTMLParserHandler} handler */
127
154
  function buildAttrRegex(handler) {
128
155
  const unquotedValue = handler.continueOnParseError ? singleAttrValueLenientUnquoted : singleAttrValues[2];
@@ -202,7 +229,7 @@ export class HTMLParser {
202
229
  const fullHtml = this.html;
203
230
  const fullLength = fullHtml.length;
204
231
 
205
- /** @type {Array<{tag: string, lowerTag: string, attrs: HTMLAttribute[]}>} */
232
+ /** @type {Array<{tag: string, lowerTag: string, attrs: HTMLAttribute[], namespace: string}>} */
206
233
  const stack = [];
207
234
  /** @type {string} */
208
235
  let lastTag = '';
@@ -225,7 +252,7 @@ export class HTMLParser {
225
252
  const startTagOpenY = new RegExp(startTagOpen.source.slice(1), 'y');
226
253
  // `\s*` with sticky flag is O(n) at worst—no retry from different positions possible
227
254
  const startTagCloseY = /\s*(\/?)>/y;
228
- const endTagY = new RegExp(endTag.source.slice(1), 'y');
255
+ const endTagOpenY = new RegExp(endTagOpen.source.slice(1), 'y');
229
256
  const doctypeY = /<!DOCTYPE[^<>]+>/iy;
230
257
  const commentTestY = /<!--/y;
231
258
  const conditionalTestY = /<!\[/y;
@@ -238,11 +265,11 @@ export class HTMLParser {
238
265
  let pos = 0;
239
266
  let lastPos;
240
267
 
241
- // An end tag always ends at a `>`; without one, the `endTag` regex’s name run
242
- // and its `[^>]*` tail overlap and backtrack O(n²) on a long unclosed name
243
- // (e.g., `</aaaa…` with no `>`). Track the next `>` monotonically—`pos` only
244
- // advances, so the aggregate scan work stays O(n)—and skip the regex when none
245
- // lies ahead, where it could not match anyway.
268
+ // An end tag always ends at a `>`; without one ahead, matching the name only to find
269
+ // no bracket behind it repeats the name run at every position, which costs O(n²) on a
270
+ // long unclosed name (e.g., `</aaaa…` with no `>`). Track the next `>` monotonically—
271
+ // `pos` only advances, so the aggregate scan work stays O(n)—and skip the match when
272
+ // none lies ahead, where the tag could not be complete anyway.
246
273
  let nextGtPos = fullHtml.indexOf('>');
247
274
  const hasCloseAtOrAfter = (/** @type {number} */ p) => {
248
275
  if (nextGtPos !== -1 && nextGtPos < p) {
@@ -251,6 +278,13 @@ export class HTMLParser {
251
278
  return nextGtPos !== -1;
252
279
  };
253
280
 
281
+ // A `-->` that the opener at `pos` does not find is not there for any later one, either,
282
+ // and the same holds for the `]>` of a downlevel-revealed conditional comment. `pos`
283
+ // only advances, so remembering the search that came up empty keeps the aggregate work
284
+ // O(n), where searching again at every opener rescans the rest of the input each time.
285
+ let commentEndAhead = true;
286
+ let conditionalEndAhead = true;
287
+
254
288
  // Helper to advance position
255
289
  const advance = (/** @type {number} */ n) => { pos += n; };
256
290
 
@@ -274,11 +308,50 @@ export class HTMLParser {
274
308
  return fullHtml.slice(startPos);
275
309
  };
276
310
 
311
+ // `annotation-xml` holds HTML only where its `encoding` says so; with any other value,
312
+ // and with none, its content stays MathML
313
+ const annotationHoldsHTML = (/** @type {{attrs?: HTMLAttribute[]}} */ entry) => {
314
+ for (const attr of entry.attrs ?? []) {
315
+ if (attr.name.toLowerCase() === 'encoding') {
316
+ return RE_HTML_ENCODING.test(attr.value ?? '');
317
+ }
318
+ }
319
+ return false;
320
+ };
321
+
322
+ // Escapable raw text is an HTML rule, so what decides it is the namespace the element sits
323
+ // in. Walking down from the root resolves that: `<svg>`/`<math>` lead out of HTML, an
324
+ // integration point leads back in, and a name counts only in the namespace it belongs to
325
+ // (`title` is one in SVG but not in MathML, `annotation-xml` one in MathML but not in SVG)
326
+ /** @param {{lowerTag: string, namespace: string, attrs?: HTMLAttribute[]} | undefined} entry */
327
+ const namespaceInside = (entry) => {
328
+ if (!entry) {
329
+ return '';
330
+ }
331
+ const { namespace, lowerTag } = entry;
332
+ if (!namespace) {
333
+ return lowerTag === 'svg' || lowerTag === 'math' ? lowerTag : '';
334
+ }
335
+ if (namespace === 'svg') {
336
+ return svgIntegrationPoints.has(lowerTag) ? '' : namespace;
337
+ }
338
+ return mathIntegrationPoints.has(lowerTag) || (lowerTag === 'annotation-xml' && annotationHoldsHTML(entry)) ? '' : namespace;
339
+ };
340
+
341
+ // The element itself never decides this: `<svg><title>` is SVG, what it holds is HTML
342
+ const inForeignContent = () => Boolean(stack[stack.length - 1]?.namespace);
343
+
344
+ // Whether the content of the element being parsed is read as text rather than markup
345
+ // (`script` and `style` hold text in every namespace; the rest do so as HTML elements only)
346
+ const holdsRawText = (/** @type {string} */ tag) =>
347
+ special.has(tag) ||
348
+ ((genericRawTextElements.has(tag) || escapableRawTextElements.has(tag)) && !inForeignContent());
349
+
277
350
  while (pos < fullLength) {
278
351
  lastPos = pos;
279
352
 
280
- // Make sure not to be in a `script` or `style` element
281
- if (!lastTagLower || !special.has(lastTagLower)) {
353
+ // Make sure not to be in an element whose content is text, not markup
354
+ if (!lastTagLower || !holdsRawText(lastTagLower)) {
282
355
  const textEnd = fullHtml.indexOf('<', pos);
283
356
 
284
357
  if (textEnd === pos) {
@@ -298,9 +371,9 @@ export class HTMLParser {
298
371
  const endTagMatch = cachedNextEndTag.match;
299
372
  cachedNextStartTag = null;
300
373
  cachedNextEndTag = null;
301
- advance((endTagMatch[0] ?? '').length);
302
- await parseEndTag(endTagMatch[0] ?? '', endTagMatch[1] ?? '');
303
- prevTag = '/' + (endTagMatch[1] ?? '').toLowerCase();
374
+ advance(endTagMatch.text.length);
375
+ await parseEndTag(endTagMatch.text, endTagMatch.name);
376
+ prevTag = '/' + endTagMatch.name.toLowerCase();
304
377
  prevAttrs = [];
305
378
  continue;
306
379
  }
@@ -310,7 +383,8 @@ export class HTMLParser {
310
383
  // Comment
311
384
  commentTestY.lastIndex = pos;
312
385
  if (commentTestY.test(fullHtml)) {
313
- const commentEnd = fullHtml.indexOf('-->', pos + 4);
386
+ const commentEnd = commentEndAhead ? fullHtml.indexOf('-->', pos + 4) : -1;
387
+ if (commentEnd === -1) commentEndAhead = false;
314
388
 
315
389
  if (commentEnd >= 0) {
316
390
  if (handler.comment) {
@@ -327,7 +401,8 @@ export class HTMLParser {
327
401
  // https://web.archive.org/web/20241201212701/https://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
328
402
  conditionalTestY.lastIndex = pos;
329
403
  if (conditionalTestY.test(fullHtml)) {
330
- const conditionalEnd = fullHtml.indexOf(']>', pos + 3);
404
+ const conditionalEnd = conditionalEndAhead ? fullHtml.indexOf(']>', pos + 3) : -1;
405
+ if (conditionalEnd === -1) conditionalEndAhead = false;
331
406
 
332
407
  if (conditionalEnd >= 0) {
333
408
  if (handler.comment) {
@@ -354,15 +429,14 @@ export class HTMLParser {
354
429
  continue;
355
430
  }
356
431
 
357
- // End tag—skip when no `>` lies ahead: The regex cannot match, and would
358
- // otherwise backtrack quadratically on a long unclosed name
432
+ // End tag—skip when no `>` lies ahead: The tag cannot be complete, and matching
433
+ // its name at every position would cost O(n²) on a long unclosed name
359
434
  if (hasCloseAtOrAfter(pos)) {
360
- endTagY.lastIndex = pos;
361
- const endTagMatch = endTagY.exec(fullHtml);
435
+ const endTagMatch = matchEndTag(pos);
362
436
  if (endTagMatch) {
363
- advance((endTagMatch[0] ?? '').length);
364
- await parseEndTag(endTagMatch[0] ?? '', endTagMatch[1] ?? '');
365
- prevTag = '/' + (endTagMatch[1] ?? '').toLowerCase();
437
+ advance(endTagMatch.text.length);
438
+ await parseEndTag(endTagMatch.text, endTagMatch.name);
439
+ prevTag = '/' + endTagMatch.name.toLowerCase();
366
440
  prevAttrs = [];
367
441
  continue;
368
442
  }
@@ -401,10 +475,9 @@ export class HTMLParser {
401
475
  nextAttrs = extractAttrInfo(nextStartTagMatch.attrs);
402
476
  cachedNextStartTag = { match: nextStartTagMatch, pos };
403
477
  } else if (hasCloseAtOrAfter(pos)) {
404
- endTagY.lastIndex = pos;
405
- const nextEndTagMatch = endTagY.exec(fullHtml);
478
+ const nextEndTagMatch = matchEndTag(pos);
406
479
  if (nextEndTagMatch) {
407
- nextTag = '/' + nextEndTagMatch[1];
480
+ nextTag = '/' + nextEndTagMatch.name;
408
481
  nextAttrs = [];
409
482
  cachedNextEndTag = { match: nextEndTagMatch, pos };
410
483
  } else {
@@ -425,32 +498,36 @@ export class HTMLParser {
425
498
  prevAttrs = [];
426
499
  } else {
427
500
  const stackedTag = lastTagLower;
428
- // Use pre-compiled regex for common tags (`script`, `style`, `noscript`) to avoid regex creation overhead
429
- const reStackedTag = /** @type {Record<string, RegExp>} */ (preCompiledStackedTags)[stackedTag] || /** @type {Record<string, RegExp>} */ (reCache)[stackedTag] || (/** @type {Record<string, RegExp>} */ (reCache)[stackedTag] = new RegExp('([\\s\\S]*?)\\x3c/' + stackedTag + '[^>]*>', 'i'));
501
+ const isEscapableRawText = escapableRawTextElements.has(stackedTag);
430
502
 
431
503
  const remaining = sliceFromPos(pos);
432
- const m = reStackedTag.exec(remaining);
433
- if (m && m.index === 0) {
434
- let text = m[1] ?? '';
435
- if (stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript') {
436
- text = stripDelimited(stripDelimited(text, '<!--', '-->'), '<![CDATA[', ']]>');
437
- }
504
+ const rawText = findRawTextEnd(remaining, stackedTag);
505
+ if (rawText) {
506
+ const text = rawText.content;
438
507
  if (handler.chars) {
439
- const result = handler.chars(text);
508
+ // Escapable raw text is a text node like any other, so the handler gets the tags
509
+ // around it—it collapses and trims whitespace by what stands next to the text
510
+ const result = isEscapableRawText
511
+ ? handler.chars(text, stackedTag, '/' + stackedTag, prevAttrs, [])
512
+ : handler.chars(text);
440
513
  if (isThenable(result)) await result;
441
514
  }
442
515
  // Advance HTML past the matched special tag content and its closing tag
443
- advance(m[0].length);
516
+ advance(rawText.length);
444
517
  await parseEndTag('</' + stackedTag + '>', stackedTag);
518
+ // What follows stands after that end tag, not after the start tag still named here—
519
+ // whitespace next to `textarea` stays verbatim only while the element is open
520
+ prevTag = '/' + stackedTag;
521
+ prevAttrs = [];
445
522
  } else {
446
- // No closing tag found; break to avoid an infinite loop
447
- if (handler.continueOnParseError && handler.chars && pos < fullLength) {
448
- const result = handler.chars(fullHtml[pos], prevTag, '', prevAttrs, []);
523
+ // Without an end tag of its own, the element holds the rest of the input as text
524
+ if (handler.chars && remaining) {
525
+ const result = isEscapableRawText
526
+ ? handler.chars(remaining, stackedTag, '', prevAttrs, [])
527
+ : handler.chars(remaining);
449
528
  if (isThenable(result)) await result;
450
- advance(1);
451
- } else {
452
- break;
453
529
  }
530
+ advance(remaining.length);
454
531
  }
455
532
  }
456
533
 
@@ -497,6 +574,21 @@ export class HTMLParser {
497
574
  }).filter(attr => attr.name)); // Filter out invalid entries
498
575
  }
499
576
 
577
+ /**
578
+ * @param {number} startPos
579
+ * @returns {{text: string, name: string} | null} The end tag standing there, or `null`
580
+ * where none is complete
581
+ */
582
+ function matchEndTag(startPos) {
583
+ endTagOpenY.lastIndex = startPos;
584
+ const open = endTagOpenY.exec(fullHtml);
585
+ if (!open) {
586
+ return null;
587
+ }
588
+ const close = findEndTagClose(fullHtml, startPos + open[0].length);
589
+ return close === -1 ? null : { text: fullHtml.slice(startPos, close + 1), name: open[1] ?? '' };
590
+ }
591
+
500
592
  function parseStartTag(/** @type {number} */ startPos) {
501
593
  startTagOpenY.lastIndex = startPos;
502
594
  const start = startTagOpenY.exec(fullHtml);
@@ -703,7 +795,17 @@ export class HTMLParser {
703
795
 
704
796
  if (lastTagLower === 'p' && nonPhrasing.has(lowerTagName)) {
705
797
  await parseEndTag('', lastTag);
706
- } else if (lowerTagName === 'tbody') {
798
+ }
799
+ // A row or cell start tag closes the row or cell still open in the same table,
800
+ // which may sit deeper down the stack than the element that was opened last
801
+ if (lowerTagName === 'tr') {
802
+ closeIfFoundInCurrentTable('tr');
803
+ } else if (lowerTagName === 'td' || lowerTagName === 'th') {
804
+ if (!closeIfFoundInCurrentTable('td')) {
805
+ closeIfFoundInCurrentTable('th');
806
+ }
807
+ }
808
+ if (lowerTagName === 'tbody') {
707
809
  if (!closeIfFoundInCurrentTable('tfoot')) {
708
810
  closeIfFoundInCurrentTable('thead');
709
811
  }
@@ -720,7 +822,7 @@ export class HTMLParser {
720
822
  if (lowerTagName === 'col' && findTagInCurrentTable('colgroup') < 0) {
721
823
  lastTag = 'colgroup';
722
824
  lastTagLower = 'colgroup';
723
- stack.push({ tag: lastTag, lowerTag: 'colgroup', attrs: [] });
825
+ stack.push({ tag: lastTag, lowerTag: 'colgroup', attrs: [], namespace: namespaceInside(stack[stack.length - 1]) });
724
826
  if (handler.start) {
725
827
  await handler.start(lastTag, [], false, '', true);
726
828
  }
@@ -796,7 +898,7 @@ export class HTMLParser {
796
898
  }));
797
899
 
798
900
  if (!unary) {
799
- stack.push({ tag: tagName, lowerTag: lowerTagName, attrs });
901
+ stack.push({ tag: tagName, lowerTag: lowerTagName, attrs, namespace: namespaceInside(stack[stack.length - 1]) });
800
902
  lastTag = tagName;
801
903
  lastTagLower = lowerTagName;
802
904
  unarySlash = '';
@@ -2,6 +2,8 @@
2
2
 
3
3
  const RE_WS_START = /^[ \n\r\t\f]+/;
4
4
  const RE_WS_END = /[ \n\r\t\f]+$/;
5
+ const RE_WS_ONLY = /^[ \n\r\t\f]+$/;
6
+ const RE_WS_NBSP_END = /[ \n\r\t\f\xA0]$/;
5
7
  const RE_ALL_WS_NBSP = /[ \n\r\t\f\xA0]+/g;
6
8
  const RE_NBSP_LEADING_GROUP = /(^|\xA0+)[^\xA0]+/g;
7
9
  const RE_NBSP_LEAD_GROUP = /(\xA0+)[^\xA0]+/g;
@@ -13,6 +15,17 @@ const RE_TRAILING_SEMICOLON = /;$/;
13
15
  const RE_AMP_ENTITY = /&(#?[0-9a-zA-Z]+;)/g;
14
16
  const RE_LEGACY_ENTITIES = /&((?:Iacute|aacute|uacute|plusmn|Otilde|otilde|agrave|Agrave|Yacute|yacute|Oslash|oslash|atilde|Atilde|brvbar|ccedil|Ccedil|Ograve|curren|divide|eacute|Eacute|ograve|Oacute|egrave|Egrave|Ugrave|frac12|frac14|frac34|ugrave|oacute|iacute|Ntilde|ntilde|Uacute|middot|igrave|Igrave|iquest|Aacute|cedil|laquo|micro|iexcl|Icirc|icirc|acirc|Ucirc|Ecirc|ocirc|Ocirc|ecirc|ucirc|Aring|aring|AElig|aelig|acute|pound|raquo|Acirc|times|THORN|szlig|thorn|COPY|auml|ordf|ordm|Uuml|macr|uuml|Auml|ouml|Ouml|para|nbsp|euml|quot|QUOT|Euml|yuml|cent|sect|copy|sup1|sup2|sup3|iuml|Iuml|ETH|shy|reg|not|yen|amp|AMP|REG|uml|eth|deg|gt|GT|LT|lt)(?!;)|(?:#?[0-9a-zA-Z]+;))/g;
15
17
  const RE_ESCAPE_LT = /</g;
18
+ // In escapable raw text only the element’s own end tag ends the element, so nothing else
19
+ // that `decodeEntities` decoded to a `<` needs escaping there
20
+ // (the record has no prototype, so a tag named after an inherited property—`constructor`,
21
+ // `__proto__`—finds nothing here and falls back to escaping every `<`)
22
+ const RE_ESCAPE_LT_RAW_TEXT = /** @type {Record<string, RegExp>} */ (Object.assign(Object.create(null), {
23
+ textarea: /<(?=\/textarea[\s/>])/gi,
24
+ title: /<(?=\/title[\s/>])/gi
25
+ }));
26
+ // Encodings that make an `annotation-xml` element hold HTML rather than MathML
27
+ // https://html.spec.whatwg.org/multipage/parsing.html#html-integration-point
28
+ const RE_HTML_ENCODING = /^(text\/html|application\/xhtml\+xml)$/i;
16
29
  const RE_ATTR_WS_CHECK = /[ \n\r\t\f]/;
17
30
  const RE_ATTR_WS_COLLAPSE = /[ \n\r\t\f]+/g;
18
31
  const RE_ATTR_WS_TRIM = /^[ \n\r\t\f]+|[ \n\r\t\f]+$/g;
@@ -170,12 +183,31 @@ const htmlElements = new Set(['a', 'abbr', 'acronym', 'address', 'applet', 'area
170
183
 
171
184
  const specialContentElements = new Set(['script', 'style']);
172
185
 
186
+ // Elements the parser reads as raw text as well, though only `script` and `style` are raw text
187
+ // elements by name—these are HTML’s alone, where `script` and `style` hold text in SVG, too
188
+ // https://html.spec.whatwg.org/multipage/parsing.html#generic-raw-text-element-parsing-algorithm
189
+ //
190
+ // (`noscript`, `noframes`, and `noembed` are raw text, too, but stay markup here: What they
191
+ // hold is markup to the UA that displays it—one without scripting or frames—so minifying it
192
+ // as markup keeps what that UA sees)
193
+ const genericRawTextElements = new Set(['iframe', 'xmp']);
194
+
195
+ // Escapable raw text elements, whose content is text rather than markup
196
+ // https://html.spec.whatwg.org/multipage/syntax.html#elements-2
197
+ const escapableRawTextElements = new Set(['textarea', 'title']);
198
+
199
+ // Raw text is read without resolving character references, so its text keeps them—unlike that
200
+ // of `textarea` and `title`, where they are resolved as they are anywhere else
201
+ const rawTextElements = new Set([...specialContentElements, ...genericRawTextElements]);
202
+
173
203
  // Exports
174
204
 
175
205
  export {
176
206
  // Regex patterns
177
207
  RE_WS_START,
178
208
  RE_WS_END,
209
+ RE_WS_ONLY,
210
+ RE_WS_NBSP_END,
179
211
  RE_ALL_WS_NBSP,
180
212
  RE_NBSP_LEADING_GROUP,
181
213
  RE_NBSP_LEAD_GROUP,
@@ -187,6 +219,8 @@ export {
187
219
  RE_AMP_ENTITY,
188
220
  RE_LEGACY_ENTITIES,
189
221
  RE_ESCAPE_LT,
222
+ RE_ESCAPE_LT_RAW_TEXT,
223
+ RE_HTML_ENCODING,
190
224
  RE_ATTR_WS_CHECK,
191
225
  RE_ATTR_WS_COLLAPSE,
192
226
  RE_ATTR_WS_TRIM,
@@ -236,5 +270,8 @@ export {
236
270
  htmlElements,
237
271
 
238
272
  // Special content elements
239
- specialContentElements
273
+ specialContentElements,
274
+ genericRawTextElements,
275
+ escapableRawTextElements,
276
+ rawTextElements
240
277
  };
package/src/lib/utils.js CHANGED
@@ -814,17 +814,18 @@ function describeQuantifierRisk(pattern) {
814
814
  * over quoted attribute values (which may contain `>`).
815
815
  * @param {string} html
816
816
  * @param {number} pos - Start position (just after the tag name)
817
+ * @param {number} [limit] - Position to stop the search at (exclusive)
817
818
  * @returns {number} Index of the closing `>`, or -1 if not found
818
819
  */
819
- function findTagEnd(html, pos) {
820
+ function findTagEnd(html, pos, limit = html.length) {
820
821
  let i = pos;
821
- while (i < html.length) {
822
+ while (i < limit) {
822
823
  const ch = html[i];
823
824
  if (ch === '>') return i;
824
825
  if (ch === '"' || ch === "'") {
825
826
  const q = ch;
826
827
  i++;
827
- while (i < html.length && html[i] !== q) i++;
828
+ while (i < limit && html[i] !== q) i++;
828
829
  }
829
830
  i++;
830
831
  }
@@ -237,8 +237,10 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
237
237
 
238
238
  // Collapse/trim whitespace for given tag
239
239
 
240
- const noCollapseWhitespaceTags = new Set(['script', 'style', 'pre', 'textarea']);
241
- const noTrimWhitespaceTags = new Set(['pre', 'textarea']);
240
+ // `xmp`, `listing`, and `plaintext` render preformatted, as `pre` does
241
+ // https://html.spec.whatwg.org/multipage/rendering.html#the-page
242
+ const noCollapseWhitespaceTags = new Set(['script', 'style', 'pre', 'textarea', 'xmp', 'listing', 'plaintext']);
243
+ const noTrimWhitespaceTags = new Set(['pre', 'textarea', 'xmp', 'listing', 'plaintext']);
242
244
 
243
245
  /** @param {string} tag */
244
246
  function canCollapseWhitespace(tag) {