html-minifier-next 2.1.4 → 2.1.6

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
@@ -1,7 +1,7 @@
1
1
  # HTML Minifier Next
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/html-minifier-next.svg)](https://www.npmjs.com/package/html-minifier-next)
4
- [![Build status](https://github.com/j9t/html-minifier-next/workflows/CI/badge.svg)](https://github.com/j9t/html-minifier-next/actions?workflow=CI)
4
+ [![Build status](https://github.com/j9t/html-minifier-next/workflows/Tests/badge.svg)](https://github.com/j9t/html-minifier-next/actions)
5
5
 
6
6
  HTML Minifier Next (HMN) is a highly **configurable, well-tested, JavaScript-based HTML minifier**.
7
7
 
@@ -132,7 +132,7 @@ class HTMLParser {
132
132
  if (!lastTag || !special.has(lastTag)) {
133
133
  let textEnd = html.indexOf('<');
134
134
  if (textEnd === 0) {
135
- // Comment:
135
+ // Comment
136
136
  if (/^<!--/.test(html)) {
137
137
  const commentEnd = html.indexOf('-->');
138
138
 
@@ -160,7 +160,7 @@ class HTMLParser {
160
160
  }
161
161
  }
162
162
 
163
- // Doctype:
163
+ // Doctype
164
164
  const doctypeMatch = html.match(doctype);
165
165
  if (doctypeMatch) {
166
166
  if (handler.doctype) {
@@ -171,7 +171,7 @@ class HTMLParser {
171
171
  continue;
172
172
  }
173
173
 
174
- // End tag:
174
+ // End tag
175
175
  const endTagMatch = html.match(endTag);
176
176
  if (endTagMatch) {
177
177
  html = html.substring(endTagMatch[0].length);
@@ -180,7 +180,7 @@ class HTMLParser {
180
180
  continue;
181
181
  }
182
182
 
183
- // Start tag:
183
+ // Start tag
184
184
  const startTagMatch = parseStartTag(html);
185
185
  if (startTagMatch) {
186
186
  html = startTagMatch.rest;
@@ -273,11 +273,41 @@ class HTMLParser {
273
273
  }
274
274
  }
275
275
 
276
- async function closeIfFound(tagName) {
277
- if (findTag(tagName) >= 0) {
278
- await parseEndTag('', tagName);
276
+ function findTagInCurrentTable(tagName) {
277
+ let pos;
278
+ const needle = tagName.toLowerCase();
279
+ for (pos = stack.length - 1; pos >= 0; pos--) {
280
+ const currentTag = stack[pos].tag.toLowerCase();
281
+ if (currentTag === needle) {
282
+ return pos;
283
+ }
284
+ // Stop searching if we hit a table boundary
285
+ if (currentTag === 'table') {
286
+ break;
287
+ }
288
+ }
289
+ return -1;
290
+ }
291
+
292
+ async function parseEndTagAt(pos) {
293
+ // Close all open elements up to pos (mirrors parseEndTag’s core branch)
294
+ for (let i = stack.length - 1; i >= pos; i--) {
295
+ if (handler.end) {
296
+ await handler.end(stack[i].tag, stack[i].attrs, true);
297
+ }
298
+ }
299
+ stack.length = pos;
300
+ lastTag = pos && stack[pos - 1].tag;
301
+ }
302
+
303
+ async function closeIfFoundInCurrentTable(tagName) {
304
+ const pos = findTagInCurrentTable(tagName);
305
+ if (pos >= 0) {
306
+ // Close at the specific index to avoid re-searching
307
+ await parseEndTagAt(pos);
279
308
  return true;
280
309
  }
310
+ return false;
281
311
  }
282
312
 
283
313
  async function handleStartTag(match) {
@@ -288,10 +318,15 @@ class HTMLParser {
288
318
  if (lastTag === 'p' && nonPhrasing.has(tagName)) {
289
319
  await parseEndTag('', lastTag);
290
320
  } else if (tagName === 'tbody') {
291
- await closeIfFound('thead');
321
+ await closeIfFoundInCurrentTable('thead');
292
322
  } else if (tagName === 'tfoot') {
293
- if (!await closeIfFound('tbody')) {
294
- await closeIfFound('thead');
323
+ if (!await closeIfFoundInCurrentTable('tbody')) {
324
+ await closeIfFoundInCurrentTable('thead');
325
+ }
326
+ } else if (tagName === 'thead') {
327
+ // If a `tbody` or `tfoot` is open in the current table, close it
328
+ if (!await closeIfFoundInCurrentTable('tbody')) {
329
+ await closeIfFoundInCurrentTable('tfoot');
295
330
  }
296
331
  }
297
332
  if (tagName === 'col' && findTag('colgroup') < 0) {
@@ -549,9 +584,9 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll) {
549
584
  }
550
585
 
551
586
  // Non-empty elements that will maintain whitespace around them
552
- const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
587
+ const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
553
588
  // Non-empty elements that will maintain whitespace within them
554
- const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 'rp', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
589
+ const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
555
590
  // Elements that will always maintain whitespace around them
556
591
  const inlineElementsToKeepWhitespace = new Set(['comment', 'img', 'input', 'wbr']);
557
592
 
@@ -904,19 +939,18 @@ async function processScript(text, options, currentAttrs) {
904
939
  return text;
905
940
  }
906
941
 
907
- // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
908
- // with the following deviations:
942
+ // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags with the following extensions:
909
943
  // - retain <body> if followed by <noscript>
910
- // - </rb>, </rt>, </rtc>, </rp>, and </tfoot> follow https://www.w3.org/TR/html5/syntax.html#optional-tags
944
+ // - <rb>, <rt>, <rtc>, <rp> follow HTML Ruby Markup Extensions draft (https://www.w3.org/TR/html-ruby-extensions/)
911
945
  // - retain all tags which are adjacent to non-standard HTML tags
912
946
  const optionalStartTags = new Set(['html', 'head', 'body', 'colgroup', 'tbody']);
913
947
  const optionalEndTags = new Set(['html', 'head', 'body', 'li', 'dt', 'dd', 'p', 'rb', 'rt', 'rtc', 'rp', 'optgroup', 'option', 'colgroup', 'caption', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th']);
914
948
  const headerTags = new Set(['meta', 'link', 'script', 'style', 'template', 'noscript']);
915
949
  const descriptionTags = new Set(['dt', 'dd']);
916
- const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul']);
950
+ const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'search', 'section', 'table', 'ul']);
917
951
  const pInlineTags = new Set(['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video']);
918
- const rubyTags = new Set(['rb', 'rt', 'rtc', 'rp']);
919
- const rtcTag = new Set(['rb', 'rtc', 'rp']);
952
+ const rubyEndTagOmission = new Set(['rb', 'rt', 'rtc', 'rp']); // </rb>, </rt>, </rp> can be omitted if followed by <rb>, <rt>, <rtc>, or <rp>
953
+ const rubyRtcEndTagOmission = new Set(['rb', 'rtc']); // </rtc> can be omitted if followed by <rb> or <rtc> (not <rt> or <rp>)
920
954
  const optionTag = new Set(['option', 'optgroup']);
921
955
  const tableContentTags = new Set(['tbody', 'tfoot']);
922
956
  const tableSectionTags = new Set(['thead', 'tbody', 'tfoot']);
@@ -972,9 +1006,9 @@ function canRemovePrecedingTag(optionalEndTag, tag) {
972
1006
  case 'rb':
973
1007
  case 'rt':
974
1008
  case 'rp':
975
- return rubyTags.has(tag);
1009
+ return rubyEndTagOmission.has(tag);
976
1010
  case 'rtc':
977
- return rtcTag.has(tag);
1011
+ return rubyRtcEndTagOmission.has(tag);
978
1012
  case 'option':
979
1013
  return optionTag.has(tag);
980
1014
  case 'thead':
@@ -1584,7 +1618,7 @@ async function minifyHTML(value, options, partialMarkup) {
1584
1618
  let optional = options.removeOptionalTags;
1585
1619
  if (optional) {
1586
1620
  const htmlTag = htmlTags.has(tag);
1587
- // <html> may be omitted if first thing inside is not comment
1621
+ // <html> may be omitted if first thing inside is not a comment
1588
1622
  // <head> may be omitted if first thing inside is an element
1589
1623
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
1590
1624
  // <colgroup> may be omitted if first thing inside is <col>
@@ -1603,7 +1637,7 @@ async function minifyHTML(value, options, partialMarkup) {
1603
1637
  optionalEndTag = '';
1604
1638
  }
1605
1639
 
1606
- // Set whitespace flags for nested tags (eg. <code> within a <pre>)
1640
+ // Set whitespace flags for nested tags (e.g., <code> within a <pre>)
1607
1641
  if (options.collapseWhitespace) {
1608
1642
  if (!stackNoTrimWhitespace.length) {
1609
1643
  squashTrailingWhitespace(tag);
@@ -1771,7 +1805,7 @@ async function minifyHTML(value, options, partialMarkup) {
1771
1805
  text = await options.minifyCSS(text);
1772
1806
  }
1773
1807
  if (options.removeOptionalTags && text) {
1774
- // <html> may be omitted if first thing inside is not comment
1808
+ // <html> may be omitted if first thing inside is not a comment
1775
1809
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
1776
1810
  if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(text))) {
1777
1811
  removeStartTag();
@@ -1782,7 +1816,10 @@ async function minifyHTML(value, options, partialMarkup) {
1782
1816
  if (compactTags.has(optionalEndTag) || (looseTags.has(optionalEndTag) && !/^\s/.test(text))) {
1783
1817
  removeEndTag();
1784
1818
  }
1785
- optionalEndTag = '';
1819
+ // Don’t reset optionalEndTag if text is only whitespace and will be collapsed (not conservatively)
1820
+ if (!/^\s+$/.test(text) || !options.collapseWhitespace || options.conservativeCollapse) {
1821
+ optionalEndTag = '';
1822
+ }
1786
1823
  }
1787
1824
  charsPrevTag = /^\s*$/.test(text) ? prevTag : 'comment';
1788
1825
  if (options.decodeEntities && text && !specialContentTags.has(currentTag)) {
@@ -1836,7 +1873,7 @@ async function minifyHTML(value, options, partialMarkup) {
1836
1873
  await parser.parse();
1837
1874
 
1838
1875
  if (options.removeOptionalTags) {
1839
- // <html> may be omitted if first thing inside is not comment
1876
+ // <html> may be omitted if first thing inside is not a comment
1840
1877
  // <head> or <body> may be omitted if empty
1841
1878
  if (topLevelTags.has(optionalStartTag)) {
1842
1879
  removeStartTag();
@@ -60322,7 +60322,7 @@ class HTMLParser {
60322
60322
  if (!lastTag || !special.has(lastTag)) {
60323
60323
  let textEnd = html.indexOf('<');
60324
60324
  if (textEnd === 0) {
60325
- // Comment:
60325
+ // Comment
60326
60326
  if (/^<!--/.test(html)) {
60327
60327
  const commentEnd = html.indexOf('-->');
60328
60328
 
@@ -60350,7 +60350,7 @@ class HTMLParser {
60350
60350
  }
60351
60351
  }
60352
60352
 
60353
- // Doctype:
60353
+ // Doctype
60354
60354
  const doctypeMatch = html.match(doctype);
60355
60355
  if (doctypeMatch) {
60356
60356
  if (handler.doctype) {
@@ -60361,7 +60361,7 @@ class HTMLParser {
60361
60361
  continue;
60362
60362
  }
60363
60363
 
60364
- // End tag:
60364
+ // End tag
60365
60365
  const endTagMatch = html.match(endTag);
60366
60366
  if (endTagMatch) {
60367
60367
  html = html.substring(endTagMatch[0].length);
@@ -60370,7 +60370,7 @@ class HTMLParser {
60370
60370
  continue;
60371
60371
  }
60372
60372
 
60373
- // Start tag:
60373
+ // Start tag
60374
60374
  const startTagMatch = parseStartTag(html);
60375
60375
  if (startTagMatch) {
60376
60376
  html = startTagMatch.rest;
@@ -60463,11 +60463,41 @@ class HTMLParser {
60463
60463
  }
60464
60464
  }
60465
60465
 
60466
- async function closeIfFound(tagName) {
60467
- if (findTag(tagName) >= 0) {
60468
- await parseEndTag('', tagName);
60466
+ function findTagInCurrentTable(tagName) {
60467
+ let pos;
60468
+ const needle = tagName.toLowerCase();
60469
+ for (pos = stack.length - 1; pos >= 0; pos--) {
60470
+ const currentTag = stack[pos].tag.toLowerCase();
60471
+ if (currentTag === needle) {
60472
+ return pos;
60473
+ }
60474
+ // Stop searching if we hit a table boundary
60475
+ if (currentTag === 'table') {
60476
+ break;
60477
+ }
60478
+ }
60479
+ return -1;
60480
+ }
60481
+
60482
+ async function parseEndTagAt(pos) {
60483
+ // Close all open elements up to pos (mirrors parseEndTag’s core branch)
60484
+ for (let i = stack.length - 1; i >= pos; i--) {
60485
+ if (handler.end) {
60486
+ await handler.end(stack[i].tag, stack[i].attrs, true);
60487
+ }
60488
+ }
60489
+ stack.length = pos;
60490
+ lastTag = pos && stack[pos - 1].tag;
60491
+ }
60492
+
60493
+ async function closeIfFoundInCurrentTable(tagName) {
60494
+ const pos = findTagInCurrentTable(tagName);
60495
+ if (pos >= 0) {
60496
+ // Close at the specific index to avoid re-searching
60497
+ await parseEndTagAt(pos);
60469
60498
  return true;
60470
60499
  }
60500
+ return false;
60471
60501
  }
60472
60502
 
60473
60503
  async function handleStartTag(match) {
@@ -60478,10 +60508,15 @@ class HTMLParser {
60478
60508
  if (lastTag === 'p' && nonPhrasing.has(tagName)) {
60479
60509
  await parseEndTag('', lastTag);
60480
60510
  } else if (tagName === 'tbody') {
60481
- await closeIfFound('thead');
60511
+ await closeIfFoundInCurrentTable('thead');
60482
60512
  } else if (tagName === 'tfoot') {
60483
- if (!await closeIfFound('tbody')) {
60484
- await closeIfFound('thead');
60513
+ if (!await closeIfFoundInCurrentTable('tbody')) {
60514
+ await closeIfFoundInCurrentTable('thead');
60515
+ }
60516
+ } else if (tagName === 'thead') {
60517
+ // If a `tbody` or `tfoot` is open in the current table, close it
60518
+ if (!await closeIfFoundInCurrentTable('tbody')) {
60519
+ await closeIfFoundInCurrentTable('tfoot');
60485
60520
  }
60486
60521
  }
60487
60522
  if (tagName === 'col' && findTag('colgroup') < 0) {
@@ -60739,9 +60774,9 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll) {
60739
60774
  }
60740
60775
 
60741
60776
  // Non-empty elements that will maintain whitespace around them
60742
- const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
60777
+ const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
60743
60778
  // Non-empty elements that will maintain whitespace within them
60744
- const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 'rp', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
60779
+ const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
60745
60780
  // Elements that will always maintain whitespace around them
60746
60781
  const inlineElementsToKeepWhitespace = new Set(['comment', 'img', 'input', 'wbr']);
60747
60782
 
@@ -61094,19 +61129,18 @@ async function processScript(text, options, currentAttrs) {
61094
61129
  return text;
61095
61130
  }
61096
61131
 
61097
- // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
61098
- // with the following deviations:
61132
+ // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags with the following extensions:
61099
61133
  // - retain <body> if followed by <noscript>
61100
- // - </rb>, </rt>, </rtc>, </rp>, and </tfoot> follow https://www.w3.org/TR/html5/syntax.html#optional-tags
61134
+ // - <rb>, <rt>, <rtc>, <rp> follow HTML Ruby Markup Extensions draft (https://www.w3.org/TR/html-ruby-extensions/)
61101
61135
  // - retain all tags which are adjacent to non-standard HTML tags
61102
61136
  const optionalStartTags = new Set(['html', 'head', 'body', 'colgroup', 'tbody']);
61103
61137
  const optionalEndTags = new Set(['html', 'head', 'body', 'li', 'dt', 'dd', 'p', 'rb', 'rt', 'rtc', 'rp', 'optgroup', 'option', 'colgroup', 'caption', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th']);
61104
61138
  const headerTags = new Set(['meta', 'link', 'script', 'style', 'template', 'noscript']);
61105
61139
  const descriptionTags = new Set(['dt', 'dd']);
61106
- const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul']);
61140
+ const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'search', 'section', 'table', 'ul']);
61107
61141
  const pInlineTags = new Set(['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video']);
61108
- const rubyTags = new Set(['rb', 'rt', 'rtc', 'rp']);
61109
- const rtcTag = new Set(['rb', 'rtc', 'rp']);
61142
+ const rubyEndTagOmission = new Set(['rb', 'rt', 'rtc', 'rp']); // </rb>, </rt>, </rp> can be omitted if followed by <rb>, <rt>, <rtc>, or <rp>
61143
+ const rubyRtcEndTagOmission = new Set(['rb', 'rtc']); // </rtc> can be omitted if followed by <rb> or <rtc> (not <rt> or <rp>)
61110
61144
  const optionTag = new Set(['option', 'optgroup']);
61111
61145
  const tableContentTags = new Set(['tbody', 'tfoot']);
61112
61146
  const tableSectionTags = new Set(['thead', 'tbody', 'tfoot']);
@@ -61162,9 +61196,9 @@ function canRemovePrecedingTag(optionalEndTag, tag) {
61162
61196
  case 'rb':
61163
61197
  case 'rt':
61164
61198
  case 'rp':
61165
- return rubyTags.has(tag);
61199
+ return rubyEndTagOmission.has(tag);
61166
61200
  case 'rtc':
61167
- return rtcTag.has(tag);
61201
+ return rubyRtcEndTagOmission.has(tag);
61168
61202
  case 'option':
61169
61203
  return optionTag.has(tag);
61170
61204
  case 'thead':
@@ -61774,7 +61808,7 @@ async function minifyHTML(value, options, partialMarkup) {
61774
61808
  let optional = options.removeOptionalTags;
61775
61809
  if (optional) {
61776
61810
  const htmlTag = htmlTags.has(tag);
61777
- // <html> may be omitted if first thing inside is not comment
61811
+ // <html> may be omitted if first thing inside is not a comment
61778
61812
  // <head> may be omitted if first thing inside is an element
61779
61813
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
61780
61814
  // <colgroup> may be omitted if first thing inside is <col>
@@ -61793,7 +61827,7 @@ async function minifyHTML(value, options, partialMarkup) {
61793
61827
  optionalEndTag = '';
61794
61828
  }
61795
61829
 
61796
- // Set whitespace flags for nested tags (eg. <code> within a <pre>)
61830
+ // Set whitespace flags for nested tags (e.g., <code> within a <pre>)
61797
61831
  if (options.collapseWhitespace) {
61798
61832
  if (!stackNoTrimWhitespace.length) {
61799
61833
  squashTrailingWhitespace(tag);
@@ -61961,7 +61995,7 @@ async function minifyHTML(value, options, partialMarkup) {
61961
61995
  text = await options.minifyCSS(text);
61962
61996
  }
61963
61997
  if (options.removeOptionalTags && text) {
61964
- // <html> may be omitted if first thing inside is not comment
61998
+ // <html> may be omitted if first thing inside is not a comment
61965
61999
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
61966
62000
  if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(text))) {
61967
62001
  removeStartTag();
@@ -61972,7 +62006,10 @@ async function minifyHTML(value, options, partialMarkup) {
61972
62006
  if (compactTags.has(optionalEndTag) || (looseTags.has(optionalEndTag) && !/^\s/.test(text))) {
61973
62007
  removeEndTag();
61974
62008
  }
61975
- optionalEndTag = '';
62009
+ // Don’t reset optionalEndTag if text is only whitespace and will be collapsed (not conservatively)
62010
+ if (!/^\s+$/.test(text) || !options.collapseWhitespace || options.conservativeCollapse) {
62011
+ optionalEndTag = '';
62012
+ }
61976
62013
  }
61977
62014
  charsPrevTag = /^\s*$/.test(text) ? prevTag : 'comment';
61978
62015
  if (options.decodeEntities && text && !specialContentTags.has(currentTag)) {
@@ -62026,7 +62063,7 @@ async function minifyHTML(value, options, partialMarkup) {
62026
62063
  await parser.parse();
62027
62064
 
62028
62065
  if (options.removeOptionalTags) {
62029
- // <html> may be omitted if first thing inside is not comment
62066
+ // <html> may be omitted if first thing inside is not a comment
62030
62067
  // <head> or <body> may be omitted if empty
62031
62068
  if (topLevelTags.has(optionalStartTag)) {
62032
62069
  removeStartTag();
@@ -60328,7 +60328,7 @@
60328
60328
  if (!lastTag || !special.has(lastTag)) {
60329
60329
  let textEnd = html.indexOf('<');
60330
60330
  if (textEnd === 0) {
60331
- // Comment:
60331
+ // Comment
60332
60332
  if (/^<!--/.test(html)) {
60333
60333
  const commentEnd = html.indexOf('-->');
60334
60334
 
@@ -60356,7 +60356,7 @@
60356
60356
  }
60357
60357
  }
60358
60358
 
60359
- // Doctype:
60359
+ // Doctype
60360
60360
  const doctypeMatch = html.match(doctype);
60361
60361
  if (doctypeMatch) {
60362
60362
  if (handler.doctype) {
@@ -60367,7 +60367,7 @@
60367
60367
  continue;
60368
60368
  }
60369
60369
 
60370
- // End tag:
60370
+ // End tag
60371
60371
  const endTagMatch = html.match(endTag);
60372
60372
  if (endTagMatch) {
60373
60373
  html = html.substring(endTagMatch[0].length);
@@ -60376,7 +60376,7 @@
60376
60376
  continue;
60377
60377
  }
60378
60378
 
60379
- // Start tag:
60379
+ // Start tag
60380
60380
  const startTagMatch = parseStartTag(html);
60381
60381
  if (startTagMatch) {
60382
60382
  html = startTagMatch.rest;
@@ -60469,11 +60469,41 @@
60469
60469
  }
60470
60470
  }
60471
60471
 
60472
- async function closeIfFound(tagName) {
60473
- if (findTag(tagName) >= 0) {
60474
- await parseEndTag('', tagName);
60472
+ function findTagInCurrentTable(tagName) {
60473
+ let pos;
60474
+ const needle = tagName.toLowerCase();
60475
+ for (pos = stack.length - 1; pos >= 0; pos--) {
60476
+ const currentTag = stack[pos].tag.toLowerCase();
60477
+ if (currentTag === needle) {
60478
+ return pos;
60479
+ }
60480
+ // Stop searching if we hit a table boundary
60481
+ if (currentTag === 'table') {
60482
+ break;
60483
+ }
60484
+ }
60485
+ return -1;
60486
+ }
60487
+
60488
+ async function parseEndTagAt(pos) {
60489
+ // Close all open elements up to pos (mirrors parseEndTag’s core branch)
60490
+ for (let i = stack.length - 1; i >= pos; i--) {
60491
+ if (handler.end) {
60492
+ await handler.end(stack[i].tag, stack[i].attrs, true);
60493
+ }
60494
+ }
60495
+ stack.length = pos;
60496
+ lastTag = pos && stack[pos - 1].tag;
60497
+ }
60498
+
60499
+ async function closeIfFoundInCurrentTable(tagName) {
60500
+ const pos = findTagInCurrentTable(tagName);
60501
+ if (pos >= 0) {
60502
+ // Close at the specific index to avoid re-searching
60503
+ await parseEndTagAt(pos);
60475
60504
  return true;
60476
60505
  }
60506
+ return false;
60477
60507
  }
60478
60508
 
60479
60509
  async function handleStartTag(match) {
@@ -60484,10 +60514,15 @@
60484
60514
  if (lastTag === 'p' && nonPhrasing.has(tagName)) {
60485
60515
  await parseEndTag('', lastTag);
60486
60516
  } else if (tagName === 'tbody') {
60487
- await closeIfFound('thead');
60517
+ await closeIfFoundInCurrentTable('thead');
60488
60518
  } else if (tagName === 'tfoot') {
60489
- if (!await closeIfFound('tbody')) {
60490
- await closeIfFound('thead');
60519
+ if (!await closeIfFoundInCurrentTable('tbody')) {
60520
+ await closeIfFoundInCurrentTable('thead');
60521
+ }
60522
+ } else if (tagName === 'thead') {
60523
+ // If a `tbody` or `tfoot` is open in the current table, close it
60524
+ if (!await closeIfFoundInCurrentTable('tbody')) {
60525
+ await closeIfFoundInCurrentTable('tfoot');
60491
60526
  }
60492
60527
  }
60493
60528
  if (tagName === 'col' && findTag('colgroup') < 0) {
@@ -60745,9 +60780,9 @@
60745
60780
  }
60746
60781
 
60747
60782
  // Non-empty elements that will maintain whitespace around them
60748
- const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
60783
+ const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
60749
60784
  // Non-empty elements that will maintain whitespace within them
60750
- const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 'rp', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
60785
+ const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
60751
60786
  // Elements that will always maintain whitespace around them
60752
60787
  const inlineElementsToKeepWhitespace = new Set(['comment', 'img', 'input', 'wbr']);
60753
60788
 
@@ -61100,19 +61135,18 @@
61100
61135
  return text;
61101
61136
  }
61102
61137
 
61103
- // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
61104
- // with the following deviations:
61138
+ // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags with the following extensions:
61105
61139
  // - retain <body> if followed by <noscript>
61106
- // - </rb>, </rt>, </rtc>, </rp>, and </tfoot> follow https://www.w3.org/TR/html5/syntax.html#optional-tags
61140
+ // - <rb>, <rt>, <rtc>, <rp> follow HTML Ruby Markup Extensions draft (https://www.w3.org/TR/html-ruby-extensions/)
61107
61141
  // - retain all tags which are adjacent to non-standard HTML tags
61108
61142
  const optionalStartTags = new Set(['html', 'head', 'body', 'colgroup', 'tbody']);
61109
61143
  const optionalEndTags = new Set(['html', 'head', 'body', 'li', 'dt', 'dd', 'p', 'rb', 'rt', 'rtc', 'rp', 'optgroup', 'option', 'colgroup', 'caption', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th']);
61110
61144
  const headerTags = new Set(['meta', 'link', 'script', 'style', 'template', 'noscript']);
61111
61145
  const descriptionTags = new Set(['dt', 'dd']);
61112
- const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul']);
61146
+ const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'search', 'section', 'table', 'ul']);
61113
61147
  const pInlineTags = new Set(['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video']);
61114
- const rubyTags = new Set(['rb', 'rt', 'rtc', 'rp']);
61115
- const rtcTag = new Set(['rb', 'rtc', 'rp']);
61148
+ const rubyEndTagOmission = new Set(['rb', 'rt', 'rtc', 'rp']); // </rb>, </rt>, </rp> can be omitted if followed by <rb>, <rt>, <rtc>, or <rp>
61149
+ const rubyRtcEndTagOmission = new Set(['rb', 'rtc']); // </rtc> can be omitted if followed by <rb> or <rtc> (not <rt> or <rp>)
61116
61150
  const optionTag = new Set(['option', 'optgroup']);
61117
61151
  const tableContentTags = new Set(['tbody', 'tfoot']);
61118
61152
  const tableSectionTags = new Set(['thead', 'tbody', 'tfoot']);
@@ -61168,9 +61202,9 @@
61168
61202
  case 'rb':
61169
61203
  case 'rt':
61170
61204
  case 'rp':
61171
- return rubyTags.has(tag);
61205
+ return rubyEndTagOmission.has(tag);
61172
61206
  case 'rtc':
61173
- return rtcTag.has(tag);
61207
+ return rubyRtcEndTagOmission.has(tag);
61174
61208
  case 'option':
61175
61209
  return optionTag.has(tag);
61176
61210
  case 'thead':
@@ -61780,7 +61814,7 @@
61780
61814
  let optional = options.removeOptionalTags;
61781
61815
  if (optional) {
61782
61816
  const htmlTag = htmlTags.has(tag);
61783
- // <html> may be omitted if first thing inside is not comment
61817
+ // <html> may be omitted if first thing inside is not a comment
61784
61818
  // <head> may be omitted if first thing inside is an element
61785
61819
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
61786
61820
  // <colgroup> may be omitted if first thing inside is <col>
@@ -61799,7 +61833,7 @@
61799
61833
  optionalEndTag = '';
61800
61834
  }
61801
61835
 
61802
- // Set whitespace flags for nested tags (eg. <code> within a <pre>)
61836
+ // Set whitespace flags for nested tags (e.g., <code> within a <pre>)
61803
61837
  if (options.collapseWhitespace) {
61804
61838
  if (!stackNoTrimWhitespace.length) {
61805
61839
  squashTrailingWhitespace(tag);
@@ -61967,7 +62001,7 @@
61967
62001
  text = await options.minifyCSS(text);
61968
62002
  }
61969
62003
  if (options.removeOptionalTags && text) {
61970
- // <html> may be omitted if first thing inside is not comment
62004
+ // <html> may be omitted if first thing inside is not a comment
61971
62005
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
61972
62006
  if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(text))) {
61973
62007
  removeStartTag();
@@ -61978,7 +62012,10 @@
61978
62012
  if (compactTags.has(optionalEndTag) || (looseTags.has(optionalEndTag) && !/^\s/.test(text))) {
61979
62013
  removeEndTag();
61980
62014
  }
61981
- optionalEndTag = '';
62015
+ // Don’t reset optionalEndTag if text is only whitespace and will be collapsed (not conservatively)
62016
+ if (!/^\s+$/.test(text) || !options.collapseWhitespace || options.conservativeCollapse) {
62017
+ optionalEndTag = '';
62018
+ }
61982
62019
  }
61983
62020
  charsPrevTag = /^\s*$/.test(text) ? prevTag : 'comment';
61984
62021
  if (options.decodeEntities && text && !specialContentTags.has(currentTag)) {
@@ -62032,7 +62069,7 @@
62032
62069
  await parser.parse();
62033
62070
 
62034
62071
  if (options.removeOptionalTags) {
62035
- // <html> may be omitted if first thing inside is not comment
62072
+ // <html> may be omitted if first thing inside is not a comment
62036
62073
  // <head> or <body> may be omitted if empty
62037
62074
  if (topLevelTags.has(optionalStartTag)) {
62038
62075
  removeStartTag();
@@ -6,4 +6,4 @@ var ps=2147483647,ds=/[^\x20-\x7E]/,hs=/[\x2E\u3002\uFF0E\uFF61]/g,As={overflow:
6
6
  * Modified by Juriy “kangax” Zaytsev
7
7
  * Original code by Erik Arvidsson, Mozilla Public License
8
8
  * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
9
- */class AE extends Set{has(e){return super.has(e.toLowerCase())}}const mE=/([^\s"'<>/=]+)/,gE=[/=/],_E=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^ \t\n\f\r"'`=<>]+)/.source],EE=function(){const e="A-Za-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u0131\\u0134-\\u013E\\u0141-\\u0148\\u014A-\\u017E\\u0180-\\u01C3\\u01CD-\\u01F0\\u01F4\\u01F5\\u01FA-\\u0217\\u0250-\\u02A8\\u02BB-\\u02C1\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03D0-\\u03D6\\u03DA\\u03DC\\u03DE\\u03E0\\u03E2-\\u03F3\\u0401-\\u040C\\u040E-\\u044F\\u0451-\\u045C\\u045E-\\u0481\\u0490-\\u04C4\\u04C7\\u04C8\\u04CB\\u04CC\\u04D0-\\u04EB\\u04EE-\\u04F5\\u04F8\\u04F9\\u0531-\\u0556\\u0559\\u0561-\\u0586\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u063A\\u0641-\\u064A\\u0671-\\u06B7\\u06BA-\\u06BE\\u06C0-\\u06CE\\u06D0-\\u06D3\\u06D5\\u06E5\\u06E6\\u0905-\\u0939\\u093D\\u0958-\\u0961\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8B\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AE0\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B36-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB5\\u0BB7-\\u0BB9\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D60\\u0D61\\u0E01-\\u0E2E\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E45\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD\\u0EAE\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0F40-\\u0F47\\u0F49-\\u0F69\\u10A0-\\u10C5\\u10D0-\\u10F6\\u1100\\u1102\\u1103\\u1105-\\u1107\\u1109\\u110B\\u110C\\u110E-\\u1112\\u113C\\u113E\\u1140\\u114C\\u114E\\u1150\\u1154\\u1155\\u1159\\u115F-\\u1161\\u1163\\u1165\\u1167\\u1169\\u116D\\u116E\\u1172\\u1173\\u1175\\u119E\\u11A8\\u11AB\\u11AE\\u11AF\\u11B7\\u11B8\\u11BA\\u11BC-\\u11C2\\u11EB\\u11F0\\u11F9\\u1E00-\\u1E9B\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2126\\u212A\\u212B\\u212E\\u2180-\\u2182\\u3007\\u3021-\\u3029\\u3041-\\u3094\\u30A1-\\u30FA\\u3105-\\u312C\\u4E00-\\u9FA5\\uAC00-\\uD7A3",t="["+e+"_]["+e+"0-9\\u0660-\\u0669\\u06F0-\\u06F9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE7-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\.\\-_\\u0300-\\u0345\\u0360\\u0361\\u0483-\\u0486\\u0591-\\u05A1\\u05A3-\\u05B9\\u05BB-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u064B-\\u0652\\u0670\\u06D6-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0901-\\u0903\\u093C\\u093E-\\u094D\\u0951-\\u0954\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A02\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A70\\u0A71\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B43\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B82\\u0B83\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C82\\u0C83\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86-\\u0F8B\\u0F90-\\u0F95\\u0F97\\u0F99-\\u0FAD\\u0FB1-\\u0FB7\\u0FB9\\u20D0-\\u20DC\\u20E1\\u302A-\\u302F\\u3099\\u309A\\xB7\\u02D0\\u02D1\\u0387\\u0640\\u0E46\\u0EC6\\u3005\\u3031-\\u3035\\u309D\\u309E\\u30FC-\\u30FE]*";return"((?:"+t+"\\:)?"+t+")"}(),vE=new RegExp("^<"+EE),bE=/^\s*(\/?)>/,yE=new RegExp("^<\\/"+EE+"[^>]*>"),SE=/^<!DOCTYPE\s?[^>]+>/i;let CE=!1;"x".replace(/x(.)?/g,function(e,t){CE=""===t});const DE=new AE(["area","base","basefont","br","col","embed","frame","hr","img","input","isindex","keygen","link","meta","param","source","track","wbr"]),wE=new AE(["a","abbr","acronym","applet","b","basefont","bdo","big","br","button","cite","code","del","dfn","em","font","i","iframe","img","input","ins","kbd","label","map","noscript","object","q","s","samp","script","select","small","span","strike","strong","sub","sup","svg","textarea","tt","u","var"]),RE=new AE(["colgroup","dd","dt","li","option","p","td","tfoot","th","thead","tr","source"]),TE=new AE(["checked","compact","declare","defer","disabled","ismap","multiple","nohref","noresize","noshade","nowrap","readonly","selected"]),OE=new AE(["script","style"]),IE=new AE(["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"]),kE={};function FE(e){let t=mE.source+"(?:\\s*("+function(e){return gE.concat(e.customAttrAssign||[]).map(function(e){return"(?:"+e.source+")"}).join("|")}(e)+")[ \\t\\n\\f\\r]*(?:"+_E.join("|")+"))?";if(e.customAttrSurround){const n=[];for(let r=e.customAttrSurround.length-1;r>=0;r--)n[r]="(?:("+e.customAttrSurround[r][0].source+")\\s*"+t+"\\s*("+e.customAttrSurround[r][1].source+"))";n.push("(?:"+t+")"),t="(?:"+n.join("|")+")"}return new RegExp("^\\s*"+t)}class xE{constructor(e,t){this.html=e,this.handler=t}async parse(){let e=this.html;const t=this.handler,n=[];let r;const i=FE(t);let o,a,s;for(;e;){if(o=e,r&&OE.has(r)){const n=r.toLowerCase(),i=kE[n]||(kE[n]=new RegExp("([\\s\\S]*?)</"+n+"[^>]*>","i"));e=await hE(e,i,async(e,r)=>("script"!==n&&"style"!==n&&"noscript"!==n&&(r=r.replace(/<!--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),t.chars&&await t.chars(r),"")),await p("</"+n+">",n)}else{let n,r=e.indexOf("<");if(0===r){if(/^<!--/.test(e)){const n=e.indexOf("--\x3e");if(n>=0){t.comment&&await t.comment(e.substring(4,n)),e=e.substring(n+3),a="";continue}}if(/^<!\[/.test(e)){const n=e.indexOf("]>");if(n>=0){t.comment&&await t.comment(e.substring(2,n+1),!0),e=e.substring(n+2),a="";continue}}const n=e.match(SE);if(n){t.doctype&&t.doctype(n[0]),e=e.substring(n[0].length),a="";continue}const i=e.match(yE);if(i){e=e.substring(i[0].length),await hE(i[0],yE,p),a="/"+i[1].toLowerCase();continue}const o=u(e);if(o){e=o.rest,await l(o),a=o.tagName.toLowerCase();continue}t.continueOnParseError&&(r=e.indexOf("<",1))}r>=0?(n=e.substring(0,r),e=e.substring(r)):(n=e,e="");let i=u(e);i?s=i.tagName:(i=e.match(yE),s=i?"/"+i[1]:""),t.chars&&await t.chars(n,a,s),a=""}if(e===o)throw new Error("Parse Error: "+e)}function u(e){const t=e.match(vE);if(t){const n={tagName:t[1],attrs:[]};let r,o;for(e=e.slice(t[0].length);!(r=e.match(bE))&&(o=e.match(i));)e=e.slice(o[0].length),n.attrs.push(o);if(r)return n.unarySlash=r[1],n.rest=e.slice(r[0].length),n}}async function c(e){if(f(e)>=0)return await p("",e),!0}async function l(e){const i=e.tagName;let o=e.unarySlash;if(t.html5&&("p"===r&&IE.has(i)?await p("",r):"tbody"===i?await c("thead"):"tfoot"===i&&(await c("tbody")||await c("thead")),"col"===i&&f("colgroup")<0&&(r="colgroup",n.push({tag:r,attrs:[]}),t.start&&await t.start(r,[],!1,""))),!t.html5&&!wE.has(i))for(;r&&wE.has(r);)await p("",r);RE.has(i)&&r===i&&await p("",i);const a=DE.has(i)||"html"===i&&"head"===r||!!o,s=e.attrs.map(function(e){let n,r,i,o,a,s;function u(t){return a=e[t],r=e[t+1],void 0!==r?'"':(r=e[t+2],void 0!==r?"'":(r=e[t+3],void 0===r&&TE.has(n)&&(r=n),""))}CE&&-1===e[0].indexOf('""')&&(""===e[3]&&delete e[3],""===e[4]&&delete e[4],""===e[5]&&delete e[5]);let c=1;if(t.customAttrSurround)for(let r=0,a=t.customAttrSurround.length;r<a;r++,c+=7)if(n=e[c+1],n){s=u(c+2),i=e[c],o=e[c+6];break}return!n&&(n=e[c])&&(s=u(c+1)),{name:n,value:r,customAssign:a||"=",customOpen:i||"",customClose:o||"",quote:s||""}});a||(n.push({tag:i,attrs:s}),r=i,o=""),t.start&&await t.start(i,s,a,o)}function f(e){let t;const r=e.toLowerCase();for(t=n.length-1;t>=0&&n[t].tag.toLowerCase()!==r;t--);return t}async function p(e,i){let o;if(o=i?f(i):0,o>=0){for(let r=n.length-1;r>=o;r--)t.end&&t.end(n[r].tag,n[r].attrs,r>o||!e);n.length=o,r=o&&n[o-1].tag}else"br"===i.toLowerCase()?t.start&&await t.start(i,[],!0,""):"p"===i.toLowerCase()&&(t.start&&await t.start(i,[],!1,"",!0),t.end&&t.end(i,[]))}t.partialMarkup||await p()}}class BE{sort(e,t=0){for(let n=0,r=this.keys.length;n<r;n++){const r=this.keys[n],i=r.slice(1);let o=e.indexOf(i,t);if(-1!==o){do{o!==t&&(e.splice(o,1),e.splice(t,0,i)),t++}while(-1!==(o=e.indexOf(i,t)));return this[r].sort(e,t)}}return e}}class ME{add(e){e.forEach(t=>{const n="$"+t;this[n]||(this[n]=[],this[n].processed=0),this[n].push(e)})}createSorter(){const e=new BE;return e.keys=Object.keys(this).sort((e,t)=>{const n=this[e].length,r=this[t].length;return n<r?1:n>r||e<t?-1:e>t?1:0}).filter(t=>{if(this[t].processed<this[t].length){const n=t.slice(1),r=new ME;return this[t].forEach(e=>{let t;for(;-1!==(t=e.indexOf(n));)e.splice(t,1);e.forEach(e=>{this["$"+e].processed++}),r.add(e.slice(0))}),e[t]=r.createSorter(),!0}return!1}),e}}const NE=e=>e&&e.replace(/^[ \n\r\t\f]+/,"").replace(/[ \n\r\t\f]+$/,"");function LE(e){return e&&e.replace(/[ \n\r\t\f\xA0]+/g,function(e){return"\t"===e?"\t":e.replace(/(^|\xA0+)[^\xA0]+/g,"$1 ")})}function PE(e,t,n,r,i){let o="",a="";return t.preserveLineBreaks&&(e=e.replace(/^[ \n\r\t\f]*?[\n\r][ \n\r\t\f]*/,function(){return o="\n",""}).replace(/[ \n\r\t\f]*?[\n\r][ \n\r\t\f]*$/,function(){return a="\n",""})),n&&(e=e.replace(/^[ \n\r\t\f\xA0]+/,function(e){const n=!o&&t.conservativeCollapse;return n&&"\t"===e?"\t":e.replace(/^[^\xA0]+/,"").replace(/(\xA0+)[^\xA0]+/g,"$1 ")||(n?" ":"")})),r&&(e=e.replace(/[ \n\r\t\f\xA0]+$/,function(e){const n=!a&&t.conservativeCollapse;return n&&"\t"===e?"\t":e.replace(/[^\xA0]+(\xA0+)/g," $1").replace(/[^\xA0]+$/,"")||(n?" ":"")})),i&&(e=LE(e)),o+e+a}const UE=["a","abbr","acronym","b","bdi","bdo","big","button","cite","code","del","dfn","em","font","i","img","input","ins","kbd","label","mark","math","meter","nobr","object","output","progress","q","rp","rt","rtc","ruby","s","samp","select","small","span","strike","strong","sub","sup","svg","textarea","time","tt","u","var","wbr"],VE=new Set(["a","abbr","acronym","b","big","del","em","font","i","ins","kbd","mark","nobr","rp","s","samp","small","span","strike","strong","sub","sup","time","tt","u","var"]),KE=new Set(["comment","img","input","wbr"]);function GE(e,t,n,r,i,o){let a=t&&!KE.has(t);a&&!r.collapseInlineTagWhitespace&&(a="/"===t.charAt(0)?!i.has(t.slice(1)):!o.has(t));let s=n&&!KE.has(n);return s&&!r.collapseInlineTagWhitespace&&(s="/"===n.charAt(0)?!o.has(n.slice(1)):!i.has(n)),PE(e,r,a,s,t&&n)}function HE(e,t){for(let n=e.length;n--;)if(e[n].name.toLowerCase()===t)return!0;return!1}const WE=new Set(["text/javascript","text/ecmascript","text/jscript","application/javascript","application/x-javascript","application/ecmascript","module"]),zE=new Set(["module"]);function YE(e=""){return""===(e=NE(e.split(/;/,2)[0]).toLowerCase())||WE.has(e)}function XE(e=""){return""===(e=NE(e).toLowerCase())||"text/css"===e}function QE(e,t){if("style"!==e)return!1;for(let e=0,n=t.length;e<n;e++){if("type"===t[e].name.toLowerCase())return XE(t[e].value)}return!0}const jE=new Set(["allowfullscreen","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","truespeed","typemustmatch","visible"]),qE=new Set(["true","false"]);function ZE(e,t,n){if("link"!==e)return!1;const r=String(n).toLowerCase();for(let e=0;e<t.length;e++)if("rel"===t[e].name.toLowerCase()){if(String(t[e].value).toLowerCase().split(/\s+/).includes(r))return!0}return!1}const JE=new Set(["img","source"]);async function $E(e,t,n,r,i,o){if(function(e,t){const n=t.customEventAttributes;if(n){for(let t=n.length;t--;)if(n[t].test(e))return!0;return!1}return/^on[a-z]{3,}$/.test(e)}(t,r))return n=NE(n).replace(/^javascript:\s*/i,""),r.minifyJS(n,!0);if("class"===t)return n=NE(n),n=r.sortClassName?r.sortClassName(n):LE(n);if(function(e,t){return/^(?:a|area|link|base)$/.test(t)&&"href"===e||"img"===t&&/^(?:src|longdesc|usemap)$/.test(e)||"object"===t&&/^(?:classid|codebase|data|usemap)$/.test(e)||"q"===t&&"cite"===e||"blockquote"===t&&"cite"===e||("ins"===t||"del"===t)&&"cite"===e||"form"===t&&"action"===e||"input"===t&&("src"===e||"usemap"===e)||"head"===t&&"profile"===e||"script"===t&&("src"===e||"for"===e)}(t,e)){if(n=NE(n),ZE(e,i,"canonical"))return n;try{const e=await r.minifyURLs(n);return"string"==typeof e?e:n}catch(e){return r.log&&r.log(e),n}}else{if(function(e,t){return/^(?:a|area|object|button)$/.test(t)&&"tabindex"===e||"input"===t&&("maxlength"===e||"tabindex"===e)||"select"===t&&("size"===e||"tabindex"===e)||"textarea"===t&&/^(?:rows|cols|tabindex)$/.test(e)||"colgroup"===t&&"span"===e||"col"===t&&"span"===e||("th"===t||"td"===t)&&("rowspan"===e||"colspan"===e)}(t,e))return NE(n);if("style"===t)return(n=NE(n))&&(/;$/.test(n)&&!/&#?[0-9a-zA-Z]+;$/.test(n)&&(n=n.replace(/\s*;$/,";")),n=await r.minifyCSS(n,"inline")),n;if(function(e,t){return"srcset"===e&&JE.has(t)}(t,e))n=(await Promise.all(NE(n).split(/\s+,\s*|\s*,\s+/).map(async function(e){let t=e,n="";const i=e.match(/\s+([1-9][0-9]*w|[0-9]+(?:\.[0-9]+)?x)$/);if(i){t=t.slice(0,-i[0].length);const e=+i[1].slice(0,-1),r=i[1].slice(-1);1===e&&"x"===r||(n=" "+e+r)}try{const e=await r.minifyURLs(t);return("string"==typeof e?e:t)+n}catch(e){return r.log&&r.log(e),t+n}}))).join(", ");else if(function(e,t){if("meta"!==e)return!1;for(let e=0,n=t.length;e<n;e++)if("name"===t[e].name&&"viewport"===t[e].value)return!0}(e,i)&&"content"===t)n=n.replace(/\s+/g,"").replace(/[0-9]+\.[0-9]+/g,function(e){return(+e).toString()});else{if(function(e,t){if("meta"!==e)return!1;for(let e=0,n=t.length;e<n;e++)if("http-equiv"===t[e].name.toLowerCase()&&"content-security-policy"===t[e].value.toLowerCase())return!0}(e,i)&&"content"===t.toLowerCase())return LE(n);if(r.customAttrCollapse&&r.customAttrCollapse.test(t))n=NE(n.replace(/ ?[\n\r]+ ?/g,"").replace(/\s{2,}/g,r.conservativeCollapse?" ":""));else if("script"===e&&"type"===t)n=NE(n.replace(/\s*;\s*/g,";"));else{if(function(e,t,n){return"media"===n&&(ZE(e,t,"stylesheet")||QE(e,t))}(e,i,t))return n=NE(n),r.minifyCSS(n,"media");if("iframe"===e&&"srcdoc"===t)return function(e){return Boolean(e.collapseWhitespace||e.removeComments||e.removeOptionalTags||e.minifyJS!==Dv||e.minifyCSS!==wv||e.minifyURLs!==Dv)}(r)?o(n,r,!0):n}}}return n}function ev(e){return"/* clean-css ignore:start */"+e+"/* clean-css ignore:end */"}function tv(e,t){switch(t){case"inline":return"*{"+e+"}";case"media":return"@media "+e+"{a{top:0}}";default:return e}}const nv=new Set(["html","head","body","colgroup","tbody"]),rv=new Set(["html","head","body","li","dt","dd","p","rb","rt","rtc","rp","optgroup","option","colgroup","caption","thead","tbody","tfoot","tr","td","th"]),iv=new Set(["meta","link","script","style","template","noscript"]),ov=new Set(["dt","dd"]),av=new Set(["address","article","aside","blockquote","details","div","dl","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","main","menu","nav","ol","p","pre","section","table","ul"]),sv=new Set(["a","audio","del","ins","map","noscript","video"]),uv=new Set(["rb","rt","rtc","rp"]),cv=new Set(["rb","rtc","rp"]),lv=new Set(["option","optgroup"]),fv=new Set(["tbody","tfoot"]),pv=new Set(["thead","tbody","tfoot"]),dv=new Set(["td","th"]),hv=new Set(["html","head","body"]),Av=new Set(["html","body"]),mv=new Set(["head","colgroup","caption"]),gv=new Set(["dt","thead"]),_v=new Set(["a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","bgsound","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","command","content","data","datalist","dd","del","details","dfn","dialog","dir","div","dl","dt","element","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","image","img","input","ins","isindex","kbd","keygen","label","legend","li","link","listing","main","map","mark","marquee","menu","menuitem","meta","meter","multicol","nav","nobr","noembed","noframes","noscript","object","ol","optgroup","option","output","p","param","picture","plaintext","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr","xmp"]);const Ev=new RegExp("^(?:class|id|style|title|lang|dir|on(?:focus|blur|change|click|dblclick|mouse(?:down|up|over|move|out)|key(?:press|down|up)))$");function vv(e,t){for(let n=t.length-1;n>=0;n--)if(t[n].name===e)return!0;return!1}function bv(e){return!/^(?:script|style|pre|textarea)$/.test(e)}function yv(e){return!/^(?:pre|textarea)$/.test(e)}async function Sv(e,t,n,r){const i=r.name(e.name);let o=e.value;if(r.decodeEntities&&o&&(o=Jl(o,Ql.Strict)),!(r.removeRedundantAttributes&&function(e,t,n,r){return n=n?NE(n.toLowerCase()):"","script"===e&&"language"===t&&"javascript"===n||"form"===e&&"method"===t&&"get"===n||"input"===e&&"type"===t&&"text"===n||"script"===e&&"charset"===t&&!HE(r,"src")||"a"===e&&"name"===t&&HE(r,"id")||"area"===e&&"shape"===t&&"rect"===n}(n,i,o,t)||r.removeScriptTypeAttributes&&"script"===n&&"type"===i&&YE(o)&&!function(e=""){return e=NE(e.split(/;/,2)[0]).toLowerCase(),zE.has(e)}(o)||r.removeStyleLinkTypeAttributes&&("style"===n||"link"===n)&&"type"===i&&XE(o)||(o&&(o=await $E(n,i,o,r,t,Iv)),r.removeEmptyAttributes&&function(e,t,n,r){return!(n&&!/^\s*$/.test(n))&&("function"==typeof r.removeEmptyAttributes?r.removeEmptyAttributes(t,e):"input"===e&&"value"===t||Ev.test(t))}(n,i,o,r))))return r.decodeEntities&&o&&(o=o.replace(/&(#?[0-9a-zA-Z]+;)/g,"&amp;$1")),{attr:e,name:i,value:o}}function Cv(e,t,n,r,i){const o=e.name;let a=e.value;const s=e.attr;let u,c,l=s.quote;if(void 0===a||n.removeAttributeQuotes&&!~a.indexOf(i)&&/^[^ \t\n\f\r"'`=<>]+$/.test(a))c=!r||t||/\/$/.test(a)?a+" ":a;else{if(!n.preventAttributesEscaping){if(void 0===n.quoteCharacter){l=(a.match(/'/g)||[]).length<(a.match(/"/g)||[]).length?"'":'"'}else l="'"===n.quoteCharacter?"'":'"';a='"'===l?a.replace(/"/g,"&#34;"):a.replace(/'/g,"&#39;")}c=l+a+l,r||n.removeTagWhitespace||(c+=" ")}return void 0===a||n.collapseBooleanAttributes&&function(e,t){return jE.has(e)||"draggable"===e&&!qE.has(t)}(o.toLowerCase(),a.toLowerCase())?(u=o,r||(u+=" ")):u=o+s.customAssign+c,s.customOpen+u+s.customClose}function Dv(e){return e}function wv(e){return Promise.resolve(e)}const Rv=e=>{const t={name:function(e){return e.toLowerCase()},canCollapseWhitespace:bv,canTrimWhitespace:yv,html5:!0,ignoreCustomComments:[/^!/,/^\s*#/],ignoreCustomFragments:[/<%[\s\S]*?%>/,/<\?[\s\S]*?\?>/],includeAutoGeneratedTags:!0,log:Dv,minifyCSS:wv,minifyJS:Dv,minifyURLs:Dv};return Object.keys(e).forEach(function(n){const r=e[n];if("caseSensitive"===n)r&&(t.name=Dv);else if("log"===n)"function"==typeof r&&(t.log=r);else if("minifyCSS"===n&&"function"!=typeof r){if(!r)return;const e="object"==typeof r?r:{};t.minifyCSS=async function(n,r){const i=tv(n=await hE(n,/(url\s*\(\s*)(?:"([^"]*)"|'([^']*)'|([^\s)]+))(\s*\))/gi,async function(e,n,r,i,o,a){const s=null!=r?'"':null!=i?"'":"",u=r??i??o??"";try{const e=await t.minifyURLs(u);return n+s+("string"==typeof e?e:u)+s+a}catch(n){return t.log&&t.log(n),e}}),r);return new Promise(o=>{new Ll(e).minify(i,(e,i)=>{i.errors.length>0&&(i.errors.forEach(t.log),o(n));const a=function(e,t){let n;switch(t){case"inline":n=e.match(/^\*\{([\s\S]*)\}$/);break;case"media":n=e.match(/^@media ([\s\S]*?)\s*{[\s\S]*}$/)}return n?n[1]:e}(i.styles,r);o(a)})})}}else if("minifyJS"===n&&"function"!=typeof r){if(!r)return;const e="object"==typeof r?r:{};e.parse={...e.parse,bare_returns:!1},t.minifyJS=async function(n,r){const i=n.match(/^\s*<!--.*/),o=i?n.slice(i[0].length).replace(/\n\s*-->\s*$/,""):n;e.parse.bare_returns=r;try{const t=await async function(e,t){const n=dE(e,t);let r,i;do{i=n.next(await r),r=i.value}while(!i.done);return i.value}(o,e);return t.code.replace(/;$/,"")}catch(e){return t.log(e),n}}}else if("minifyURLs"===n&&"function"!=typeof r){if(!r)return;let e=r;"string"==typeof r?e={site:r}:"object"!=typeof r&&(e={}),t.minifyURLs=function(n){try{return Hf.relate(n,e)}catch(e){return t.log(e),n}}}else t[n]=r}),t};function Tv(e){let t;do{t=Math.random().toString(36).replace(/^0\.[0-9]*/,"")}while(~e.indexOf(t));return t}const Ov=new Set(["script","style"]);async function Iv(e,t,n){if(t.maxInputLength&&e.length>t.maxInputLength)throw new Error(`Input length (${e.length}) exceeds maximum allowed length (${t.maxInputLength})`);t.collapseWhitespace&&(e=PE(e,t,!0,!0));const r=[];let i,o,a="",s="",u=[];const c=[],l=[];let f="",p="";const d=[],h=[];let A,m,g;const _=t.inlineCustomElements??[],E=(Array.isArray(_)?_:Array.from(_)).map(e=>t.name(e)),v=new Set([...VE,...E]),b=new Set([...UE,...E]);e=e.replace(/<!-- htmlmin:ignore -->([\s\S]*?)<!-- htmlmin:ignore -->/g,function(n,r){if(!A){A=Tv(e);const n=new RegExp("^"+A+"([0-9]+)$");t.ignoreCustomComments?t.ignoreCustomComments=t.ignoreCustomComments.slice():t.ignoreCustomComments=[],t.ignoreCustomComments.push(n)}const i="\x3c!--"+A+d.length+"--\x3e";return d.push(r),i});const y=t.ignoreCustomFragments.map(function(e){return e.source});if(y.length){for(let e=0;e<y.length;e++)if(/[*+]/.test(y[e])){t.log("Warning: Custom fragment contains unlimited quantifiers (* or +) which may cause ReDoS vulnerability");break}const n=t.customFragmentQuantifierLimit||200,r=`\\s{0,${n}}`,i=new RegExp(r+"(?:"+y.join("|")+"){1,"+n+"}"+r,"g");e=e.replace(i,function(n){var r;m||(m=Tv(e),g=new RegExp("(\\s*)"+m+"([0-9]+)"+m+"(\\s*)","g"),t.minifyCSS&&(t.minifyCSS=(r=t.minifyCSS,function(e,t){e=e.replace(g,function(e,t,n){const r=h[+n];return r[1]+m+n+m+r[2]});const n=[];return(new Ll).minify(tv(e,t)).warnings.forEach(function(t){const r=g.exec(t);if(r){const t=m+r[2]+m;e=e.replace(t,ev(t)),n.push(t)}}),r(e,t).then(e=>(n.forEach(function(t){e=e.replace(ev(t),t)}),e))})),t.minifyJS&&(t.minifyJS=function(e){return function(t,n){return e(t.replace(g,function(e,t,n){const r=h[+n];return r[1]+m+n+m+r[2]}),n)}}(t.minifyJS)));const i=m+h.length+m;return h.push(/^(\s*)[\s\S]*?(\s*)$/.exec(n)),"\t"+i+"\t"})}function S(e,n){return t.canTrimWhitespace(e,n,yv)}function C(){let e=r.length-1;for(;e>0&&!/^<[^/!]/.test(r[e]);)e--;r.length=Math.max(0,e)}function D(){let e=r.length-1;for(;e>0&&!/^<\//.test(r[e]);)e--;r.length=Math.max(0,e)}function w(e,n){for(let i=null;e>=0&&S(i);e--){const o=r[e],a=o.match(/^<\/([\w:-]+)>$/);if(a)i=a[1];else if(/>$/.test(o)||(r[e]=GE(o,null,n,t,b,v)))break}}function R(e){let t=r.length-1;if(r.length>1){const e=r[r.length-1];/^(?:<!|$)/.test(e)&&-1===e.indexOf(A)&&t--}w(t,e)}(t.sortAttributes&&"function"!=typeof t.sortAttributes||t.sortClassName&&"function"!=typeof t.sortClassName)&&await async function(e,t,n,r){const i=t.sortAttributes&&Object.create(null),o=t.sortClassName&&new ME;function a(e){return e.map(function(e){return t.name(e.name)})}function s(e,t){return!t||-1===e.indexOf(t)}function u(e){return s(e,n)&&s(e,r)}const c=t.log;if(t.log=Dv,t.sortAttributes=!1,t.sortClassName=!1,await async function e(n){let r,s;const c=new xE(n,{start:function(e,n){i&&(i[e]||(i[e]=new ME),i[e].add(a(n).filter(u)));for(let i=0,a=n.length;i<a;i++){const a=n[i];o&&a.value&&"class"===t.name(a.name)?o.add(NE(a.value).split(/[ \t\n\f\r]+/).filter(u)):t.processScripts&&"type"===a.name.toLowerCase()&&(r=e,s=a.value)}},end:function(){r=""},chars:async function(n){t.processScripts&&Ov.has(r)&&t.processScripts.indexOf(s)>-1&&await e(n)}});await c.parse()}(await Iv(e,t)),t.log=c,i){const e=Object.create(null);for(const t in i)e[t]=i[t].createSorter();t.sortAttributes=function(t,n){const r=e[t];if(r){const e=Object.create(null),t=a(n);t.forEach(function(t,r){(e[t]||(e[t]=[])).push(n[r])}),r.sort(t).forEach(function(t,r){n[r]=e[t].shift()})}}}if(o){const e=o.createSorter();t.sortClassName=function(t){return e.sort(t.split(/[ \n\f\r]+/)).join(" ")}}}(e,t,A,m);const T=new xE(e,{partialMarkup:n,continueOnParseError:t.continueOnParseError,customAttrAssign:t.customAttrAssign,customAttrSurround:t.customAttrSurround,html5:t.html5,start:async function(e,n,d,h,A){"svg"===e.toLowerCase()&&((t=Object.create(t)).caseSensitive=!0,t.keepClosingSlash=!0,t.name=Dv),e=t.name(e),s=e,i=e,v.has(e)||(a=""),o=!1,u=n;let g=t.removeOptionalTags;if(g){const t=_v.has(e);t&&function(e,t){switch(e){case"html":case"head":return!0;case"body":return!iv.has(t);case"colgroup":return"col"===t;case"tbody":return"tr"===t}return!1}(f,e)&&C(),f="",t&&function(e,t){switch(e){case"html":case"head":case"body":case"colgroup":case"caption":return!0;case"li":case"optgroup":case"tr":return t===e;case"dt":case"dd":return ov.has(t);case"p":return av.has(t);case"rb":case"rt":case"rp":return uv.has(t);case"rtc":return cv.has(t);case"option":return lv.has(t);case"thead":case"tbody":return fv.has(t);case"tfoot":return"tbody"===t;case"td":case"th":return dv.has(t)}return!1}(p,e)&&(D(),g=!function(e,t){switch(t){case"colgroup":return"colgroup"===e;case"tbody":return pv.has(e)}return!1}(p,e)),p=""}t.collapseWhitespace&&(c.length||R(e),d||(S(e,n)&&!c.length||c.push(e),function(e,n){return t.canCollapseWhitespace(e,n,bv)}(e,n)&&!l.length||l.push(e)));const _="<"+e,E=h&&t.keepClosingSlash;r.push(_),t.sortAttributes&&t.sortAttributes(e,n);const b=[];for(let r=n.length,i=!0;--r>=0;){const o=await Sv(n[r],n,e,t);o&&(b.unshift(Cv(o,E,t,i,m)),i=!1)}b.length>0?(r.push(" "),r.push.apply(r,b)):g&&nv.has(e)&&(f=e),r.push(r.pop()+(E?"/":"")+">"),A&&!t.includeAutoGeneratedTags&&(C(),f="")},end:function(e,n,u){"svg"===e.toLowerCase()&&(t=Object.getPrototypeOf(t)),e=t.name(e),t.collapseWhitespace&&(c.length?e===c[c.length-1]&&c.pop():R("/"+e),l.length&&e===l[l.length-1]&&l.pop());let d=!1;e===s&&(s="",d=!o),t.removeOptionalTags&&(d&&hv.has(f)&&C(),f="",!_v.has(e)||!p||gv.has(p)||"p"===p&&sv.has(e)||D(),p=rv.has(e)?e:""),t.removeEmptyElements&&d&&function(e,t){switch(e){case"textarea":return!1;case"audio":case"script":case"video":if(vv("src",t))return!1;break;case"iframe":if(vv("src",t)||vv("srcdoc",t))return!1;break;case"object":if(vv("data",t))return!1;break;case"applet":if(vv("code",t))return!1}return!0}(e,n)?(C(),f="",p=""):(u&&!t.includeAutoGeneratedTags?p="":r.push("</"+e+">"),i="/"+e,b.has(e)?d&&(a+="|"):a="")},chars:async function(e,n,d){if(n=""===n?"comment":n,d=""===d?"comment":d,t.decodeEntities&&e&&!Ov.has(s)&&(e=function(e,t=Ql.Legacy){return Jl(e,t)}(e)),t.collapseWhitespace){if(!c.length){if("comment"===n){const o=r[r.length-1];if(-1===o.indexOf(A)&&(o||(n=i),r.length>1&&(!o||!t.conservativeCollapse&&/ $/.test(a)))){const t=r.length-2;r[t]=r[t].replace(/\s+$/,function(t){return e=t+e,""})}}if(n)if("/nobr"===n||"wbr"===n){if(/^\s/.test(e)){let e=r.length-1;for(;e>0&&0!==r[e].lastIndexOf("<"+n);)e--;w(e-1,"br")}}else v.has("/"===n.charAt(0)?n.slice(1):n)&&(e=PE(e,t,/(?:^|\s)$/.test(a)));!(e=n||d?GE(e,n,d,t,b,v):PE(e,t,!0,!0))&&/\s$/.test(a)&&n&&"/"===n.charAt(0)&&w(r.length-1,d)}l.length||"html"===d||n&&d||(e=PE(e,t,!1,!1,!0))}t.processScripts&&Ov.has(s)&&(e=await async function(e,t,n){for(let r=0,i=n.length;r<i;r++)if("type"===n[r].name.toLowerCase()&&t.processScripts.indexOf(n[r].value)>-1)return await Iv(e,t);return e}(e,t,u)),function(e,t){if("script"!==e)return!1;for(let e=0,n=t.length;e<n;e++)if("type"===t[e].name.toLowerCase())return YE(t[e].value);return!0}(s,u)&&(e=await t.minifyJS(e)),QE(s,u)&&(e=await t.minifyCSS(e)),t.removeOptionalTags&&e&&(("html"===f||"body"===f&&!/^\s/.test(e))&&C(),f="",(Av.has(p)||mv.has(p)&&!/^\s/.test(e))&&D(),p=""),i=/^\s*$/.test(e)?n:"comment",t.decodeEntities&&e&&!Ov.has(s)&&(e=e.replace(/&((?: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,"&amp$1").replace(/</g,"&lt;")),g&&t.collapseWhitespace&&c.length&&(e=e.replace(g,function(e,t,n){return h[+n][0]})),a+=e,e&&(o=!0),r.push(e)},comment:async function(e,n){const i=n?"<!":"\x3c!--",o=n?">":"--\x3e";e=function(e){return/^\[if\s[^\]]+]|\[endif]$/.test(e)}(e)?i+await async function(e,t){return t.processConditionalComments?await hE(e,/^(\[if\s[^\]]+]>)([\s\S]*?)(<!\[endif])$/,async function(e,n,r,i){return n+await Iv(r,t,!0)+i}):e}(e,t)+o:t.removeComments?function(e,t){for(let n=0,r=t.ignoreCustomComments.length;n<r;n++)if(t.ignoreCustomComments[n].test(e))return!0;return!1}(e,t)?"\x3c!--"+e+"--\x3e":"":i+e+o,t.removeOptionalTags&&e&&(f="",p=""),r.push(e)},doctype:function(e){r.push(t.useShortDoctype?"<!doctype"+(t.removeTagWhitespace?"":" ")+"html>":LE(e))}});return await T.parse(),t.removeOptionalTags&&(hv.has(f)&&C(),p&&!gv.has(p)&&D()),t.collapseWhitespace&&R("br"),function(e,t,n,r){let i;const o=t.maxLineLength,a=t.noNewlinesBeforeTagClose;if(o){let t="";const s=[];for(;e.length;){const i=t.length,u=e[0].indexOf("\n"),c=Boolean(e[0].match(yE)),l=a&&c;u<0?t+=r(n(e.shift())):(t+=r(n(e[0].slice(0,u))),e[0]=e[0].slice(u+1)),i>0&&t.length>o&&!l?(s.push(t.slice(0,i)),t=t.slice(i)):u>=0&&(s.push(t),t="")}t&&s.push(t),i=s.join("\n")}else i=r(n(e.join("")));return t.collapseWhitespace?PE(i,t,!0,!0):i}(r,t,g?function(e){return e.replace(g,function(e,n,r,i){let o=h[+r][0];return t.collapseWhitespace?("\t"!==n&&(o=n+o),"\t"!==i&&(o+=i),PE(o,{preserveLineBreaks:t.preserveLineBreaks,conservativeCollapse:!t.trimCustomFragments},/^[ \n\r\t\f]/.test(o),/[ \n\r\t\f]$/.test(o))):o})}:Dv,A?function(e){return e.replace(new RegExp("\x3c!--"+A+"([0-9]+)--\x3e","g"),function(e,t){return d[+t]})}:Dv)}const kv=async function(e,t){const n=Date.now();t=Rv(t||{});const r=await Iv(e,t);return t.log("minified in: "+(Date.now()-n)+"ms"),r};var Fv={minify:kv};e.default=Fv,e.minify=kv,Object.defineProperty(e,"__esModule",{value:!0})});
9
+ */class AE extends Set{has(e){return super.has(e.toLowerCase())}}const mE=/([^\s"'<>/=]+)/,gE=[/=/],_E=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^ \t\n\f\r"'`=<>]+)/.source],EE=function(){const e="A-Za-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u0131\\u0134-\\u013E\\u0141-\\u0148\\u014A-\\u017E\\u0180-\\u01C3\\u01CD-\\u01F0\\u01F4\\u01F5\\u01FA-\\u0217\\u0250-\\u02A8\\u02BB-\\u02C1\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03D0-\\u03D6\\u03DA\\u03DC\\u03DE\\u03E0\\u03E2-\\u03F3\\u0401-\\u040C\\u040E-\\u044F\\u0451-\\u045C\\u045E-\\u0481\\u0490-\\u04C4\\u04C7\\u04C8\\u04CB\\u04CC\\u04D0-\\u04EB\\u04EE-\\u04F5\\u04F8\\u04F9\\u0531-\\u0556\\u0559\\u0561-\\u0586\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u063A\\u0641-\\u064A\\u0671-\\u06B7\\u06BA-\\u06BE\\u06C0-\\u06CE\\u06D0-\\u06D3\\u06D5\\u06E5\\u06E6\\u0905-\\u0939\\u093D\\u0958-\\u0961\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8B\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AE0\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B36-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB5\\u0BB7-\\u0BB9\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D60\\u0D61\\u0E01-\\u0E2E\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E45\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD\\u0EAE\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0F40-\\u0F47\\u0F49-\\u0F69\\u10A0-\\u10C5\\u10D0-\\u10F6\\u1100\\u1102\\u1103\\u1105-\\u1107\\u1109\\u110B\\u110C\\u110E-\\u1112\\u113C\\u113E\\u1140\\u114C\\u114E\\u1150\\u1154\\u1155\\u1159\\u115F-\\u1161\\u1163\\u1165\\u1167\\u1169\\u116D\\u116E\\u1172\\u1173\\u1175\\u119E\\u11A8\\u11AB\\u11AE\\u11AF\\u11B7\\u11B8\\u11BA\\u11BC-\\u11C2\\u11EB\\u11F0\\u11F9\\u1E00-\\u1E9B\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2126\\u212A\\u212B\\u212E\\u2180-\\u2182\\u3007\\u3021-\\u3029\\u3041-\\u3094\\u30A1-\\u30FA\\u3105-\\u312C\\u4E00-\\u9FA5\\uAC00-\\uD7A3",t="["+e+"_]["+e+"0-9\\u0660-\\u0669\\u06F0-\\u06F9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE7-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\.\\-_\\u0300-\\u0345\\u0360\\u0361\\u0483-\\u0486\\u0591-\\u05A1\\u05A3-\\u05B9\\u05BB-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u064B-\\u0652\\u0670\\u06D6-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0901-\\u0903\\u093C\\u093E-\\u094D\\u0951-\\u0954\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A02\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A70\\u0A71\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B43\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B82\\u0B83\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C82\\u0C83\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86-\\u0F8B\\u0F90-\\u0F95\\u0F97\\u0F99-\\u0FAD\\u0FB1-\\u0FB7\\u0FB9\\u20D0-\\u20DC\\u20E1\\u302A-\\u302F\\u3099\\u309A\\xB7\\u02D0\\u02D1\\u0387\\u0640\\u0E46\\u0EC6\\u3005\\u3031-\\u3035\\u309D\\u309E\\u30FC-\\u30FE]*";return"((?:"+t+"\\:)?"+t+")"}(),vE=new RegExp("^<"+EE),bE=/^\s*(\/?)>/,yE=new RegExp("^<\\/"+EE+"[^>]*>"),SE=/^<!DOCTYPE\s?[^>]+>/i;let CE=!1;"x".replace(/x(.)?/g,function(e,t){CE=""===t});const DE=new AE(["area","base","basefont","br","col","embed","frame","hr","img","input","isindex","keygen","link","meta","param","source","track","wbr"]),wE=new AE(["a","abbr","acronym","applet","b","basefont","bdo","big","br","button","cite","code","del","dfn","em","font","i","iframe","img","input","ins","kbd","label","map","noscript","object","q","s","samp","script","select","small","span","strike","strong","sub","sup","svg","textarea","tt","u","var"]),RE=new AE(["colgroup","dd","dt","li","option","p","td","tfoot","th","thead","tr","source"]),TE=new AE(["checked","compact","declare","defer","disabled","ismap","multiple","nohref","noresize","noshade","nowrap","readonly","selected"]),OE=new AE(["script","style"]),IE=new AE(["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"]),kE={};function FE(e){let t=mE.source+"(?:\\s*("+function(e){return gE.concat(e.customAttrAssign||[]).map(function(e){return"(?:"+e.source+")"}).join("|")}(e)+")[ \\t\\n\\f\\r]*(?:"+_E.join("|")+"))?";if(e.customAttrSurround){const n=[];for(let r=e.customAttrSurround.length-1;r>=0;r--)n[r]="(?:("+e.customAttrSurround[r][0].source+")\\s*"+t+"\\s*("+e.customAttrSurround[r][1].source+"))";n.push("(?:"+t+")"),t="(?:"+n.join("|")+")"}return new RegExp("^\\s*"+t)}class xE{constructor(e,t){this.html=e,this.handler=t}async parse(){let e=this.html;const t=this.handler,n=[];let r;const i=FE(t);let o,a,s;for(;e;){if(o=e,r&&OE.has(r)){const n=r.toLowerCase(),i=kE[n]||(kE[n]=new RegExp("([\\s\\S]*?)</"+n+"[^>]*>","i"));e=await hE(e,i,async(e,r)=>("script"!==n&&"style"!==n&&"noscript"!==n&&(r=r.replace(/<!--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),t.chars&&await t.chars(r),"")),await p("</"+n+">",n)}else{let n,r=e.indexOf("<");if(0===r){if(/^<!--/.test(e)){const n=e.indexOf("--\x3e");if(n>=0){t.comment&&await t.comment(e.substring(4,n)),e=e.substring(n+3),a="";continue}}if(/^<!\[/.test(e)){const n=e.indexOf("]>");if(n>=0){t.comment&&await t.comment(e.substring(2,n+1),!0),e=e.substring(n+2),a="";continue}}const n=e.match(SE);if(n){t.doctype&&t.doctype(n[0]),e=e.substring(n[0].length),a="";continue}const i=e.match(yE);if(i){e=e.substring(i[0].length),await hE(i[0],yE,p),a="/"+i[1].toLowerCase();continue}const o=u(e);if(o){e=o.rest,await l(o),a=o.tagName.toLowerCase();continue}t.continueOnParseError&&(r=e.indexOf("<",1))}r>=0?(n=e.substring(0,r),e=e.substring(r)):(n=e,e="");let i=u(e);i?s=i.tagName:(i=e.match(yE),s=i?"/"+i[1]:""),t.chars&&await t.chars(n,a,s),a=""}if(e===o)throw new Error("Parse Error: "+e)}function u(e){const t=e.match(vE);if(t){const n={tagName:t[1],attrs:[]};let r,o;for(e=e.slice(t[0].length);!(r=e.match(bE))&&(o=e.match(i));)e=e.slice(o[0].length),n.attrs.push(o);if(r)return n.unarySlash=r[1],n.rest=e.slice(r[0].length),n}}async function c(e){const i=function(e){let t;const r=e.toLowerCase();for(t=n.length-1;t>=0;t--){const e=n[t].tag.toLowerCase();if(e===r)return t;if("table"===e)break}return-1}(e);return i>=0&&(await async function(e){for(let r=n.length-1;r>=e;r--)t.end&&await t.end(n[r].tag,n[r].attrs,!0);n.length=e,r=e&&n[e-1].tag}(i),!0)}async function l(e){const i=e.tagName;let o=e.unarySlash;if(t.html5&&("p"===r&&IE.has(i)?await p("",r):"tbody"===i?await c("thead"):"tfoot"===i?await c("tbody")||await c("thead"):"thead"===i&&(await c("tbody")||await c("tfoot")),"col"===i&&f("colgroup")<0&&(r="colgroup",n.push({tag:r,attrs:[]}),t.start&&await t.start(r,[],!1,""))),!t.html5&&!wE.has(i))for(;r&&wE.has(r);)await p("",r);RE.has(i)&&r===i&&await p("",i);const a=DE.has(i)||"html"===i&&"head"===r||!!o,s=e.attrs.map(function(e){let n,r,i,o,a,s;function u(t){return a=e[t],r=e[t+1],void 0!==r?'"':(r=e[t+2],void 0!==r?"'":(r=e[t+3],void 0===r&&TE.has(n)&&(r=n),""))}CE&&-1===e[0].indexOf('""')&&(""===e[3]&&delete e[3],""===e[4]&&delete e[4],""===e[5]&&delete e[5]);let c=1;if(t.customAttrSurround)for(let r=0,a=t.customAttrSurround.length;r<a;r++,c+=7)if(n=e[c+1],n){s=u(c+2),i=e[c],o=e[c+6];break}return!n&&(n=e[c])&&(s=u(c+1)),{name:n,value:r,customAssign:a||"=",customOpen:i||"",customClose:o||"",quote:s||""}});a||(n.push({tag:i,attrs:s}),r=i,o=""),t.start&&await t.start(i,s,a,o)}function f(e){let t;const r=e.toLowerCase();for(t=n.length-1;t>=0&&n[t].tag.toLowerCase()!==r;t--);return t}async function p(e,i){let o;if(o=i?f(i):0,o>=0){for(let r=n.length-1;r>=o;r--)t.end&&t.end(n[r].tag,n[r].attrs,r>o||!e);n.length=o,r=o&&n[o-1].tag}else"br"===i.toLowerCase()?t.start&&await t.start(i,[],!0,""):"p"===i.toLowerCase()&&(t.start&&await t.start(i,[],!1,"",!0),t.end&&t.end(i,[]))}t.partialMarkup||await p()}}class BE{sort(e,t=0){for(let n=0,r=this.keys.length;n<r;n++){const r=this.keys[n],i=r.slice(1);let o=e.indexOf(i,t);if(-1!==o){do{o!==t&&(e.splice(o,1),e.splice(t,0,i)),t++}while(-1!==(o=e.indexOf(i,t)));return this[r].sort(e,t)}}return e}}class ME{add(e){e.forEach(t=>{const n="$"+t;this[n]||(this[n]=[],this[n].processed=0),this[n].push(e)})}createSorter(){const e=new BE;return e.keys=Object.keys(this).sort((e,t)=>{const n=this[e].length,r=this[t].length;return n<r?1:n>r||e<t?-1:e>t?1:0}).filter(t=>{if(this[t].processed<this[t].length){const n=t.slice(1),r=new ME;return this[t].forEach(e=>{let t;for(;-1!==(t=e.indexOf(n));)e.splice(t,1);e.forEach(e=>{this["$"+e].processed++}),r.add(e.slice(0))}),e[t]=r.createSorter(),!0}return!1}),e}}const NE=e=>e&&e.replace(/^[ \n\r\t\f]+/,"").replace(/[ \n\r\t\f]+$/,"");function LE(e){return e&&e.replace(/[ \n\r\t\f\xA0]+/g,function(e){return"\t"===e?"\t":e.replace(/(^|\xA0+)[^\xA0]+/g,"$1 ")})}function PE(e,t,n,r,i){let o="",a="";return t.preserveLineBreaks&&(e=e.replace(/^[ \n\r\t\f]*?[\n\r][ \n\r\t\f]*/,function(){return o="\n",""}).replace(/[ \n\r\t\f]*?[\n\r][ \n\r\t\f]*$/,function(){return a="\n",""})),n&&(e=e.replace(/^[ \n\r\t\f\xA0]+/,function(e){const n=!o&&t.conservativeCollapse;return n&&"\t"===e?"\t":e.replace(/^[^\xA0]+/,"").replace(/(\xA0+)[^\xA0]+/g,"$1 ")||(n?" ":"")})),r&&(e=e.replace(/[ \n\r\t\f\xA0]+$/,function(e){const n=!a&&t.conservativeCollapse;return n&&"\t"===e?"\t":e.replace(/[^\xA0]+(\xA0+)/g," $1").replace(/[^\xA0]+$/,"")||(n?" ":"")})),i&&(e=LE(e)),o+e+a}const UE=["a","abbr","acronym","b","bdi","bdo","big","button","cite","code","del","dfn","em","font","i","img","input","ins","kbd","label","mark","math","meter","nobr","object","output","progress","q","rb","rp","rt","rtc","ruby","s","samp","select","small","span","strike","strong","sub","sup","svg","textarea","time","tt","u","var","wbr"],VE=new Set(["a","abbr","acronym","b","big","del","em","font","i","ins","kbd","mark","nobr","s","samp","small","span","strike","strong","sub","sup","time","tt","u","var"]),KE=new Set(["comment","img","input","wbr"]);function GE(e,t,n,r,i,o){let a=t&&!KE.has(t);a&&!r.collapseInlineTagWhitespace&&(a="/"===t.charAt(0)?!i.has(t.slice(1)):!o.has(t));let s=n&&!KE.has(n);return s&&!r.collapseInlineTagWhitespace&&(s="/"===n.charAt(0)?!o.has(n.slice(1)):!i.has(n)),PE(e,r,a,s,t&&n)}function HE(e,t){for(let n=e.length;n--;)if(e[n].name.toLowerCase()===t)return!0;return!1}const WE=new Set(["text/javascript","text/ecmascript","text/jscript","application/javascript","application/x-javascript","application/ecmascript","module"]),zE=new Set(["module"]);function YE(e=""){return""===(e=NE(e.split(/;/,2)[0]).toLowerCase())||WE.has(e)}function XE(e=""){return""===(e=NE(e).toLowerCase())||"text/css"===e}function QE(e,t){if("style"!==e)return!1;for(let e=0,n=t.length;e<n;e++){if("type"===t[e].name.toLowerCase())return XE(t[e].value)}return!0}const jE=new Set(["allowfullscreen","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","truespeed","typemustmatch","visible"]),qE=new Set(["true","false"]);function ZE(e,t,n){if("link"!==e)return!1;const r=String(n).toLowerCase();for(let e=0;e<t.length;e++)if("rel"===t[e].name.toLowerCase()){if(String(t[e].value).toLowerCase().split(/\s+/).includes(r))return!0}return!1}const JE=new Set(["img","source"]);async function $E(e,t,n,r,i,o){if(function(e,t){const n=t.customEventAttributes;if(n){for(let t=n.length;t--;)if(n[t].test(e))return!0;return!1}return/^on[a-z]{3,}$/.test(e)}(t,r))return n=NE(n).replace(/^javascript:\s*/i,""),r.minifyJS(n,!0);if("class"===t)return n=NE(n),n=r.sortClassName?r.sortClassName(n):LE(n);if(function(e,t){return/^(?:a|area|link|base)$/.test(t)&&"href"===e||"img"===t&&/^(?:src|longdesc|usemap)$/.test(e)||"object"===t&&/^(?:classid|codebase|data|usemap)$/.test(e)||"q"===t&&"cite"===e||"blockquote"===t&&"cite"===e||("ins"===t||"del"===t)&&"cite"===e||"form"===t&&"action"===e||"input"===t&&("src"===e||"usemap"===e)||"head"===t&&"profile"===e||"script"===t&&("src"===e||"for"===e)}(t,e)){if(n=NE(n),ZE(e,i,"canonical"))return n;try{const e=await r.minifyURLs(n);return"string"==typeof e?e:n}catch(e){return r.log&&r.log(e),n}}else{if(function(e,t){return/^(?:a|area|object|button)$/.test(t)&&"tabindex"===e||"input"===t&&("maxlength"===e||"tabindex"===e)||"select"===t&&("size"===e||"tabindex"===e)||"textarea"===t&&/^(?:rows|cols|tabindex)$/.test(e)||"colgroup"===t&&"span"===e||"col"===t&&"span"===e||("th"===t||"td"===t)&&("rowspan"===e||"colspan"===e)}(t,e))return NE(n);if("style"===t)return(n=NE(n))&&(/;$/.test(n)&&!/&#?[0-9a-zA-Z]+;$/.test(n)&&(n=n.replace(/\s*;$/,";")),n=await r.minifyCSS(n,"inline")),n;if(function(e,t){return"srcset"===e&&JE.has(t)}(t,e))n=(await Promise.all(NE(n).split(/\s+,\s*|\s*,\s+/).map(async function(e){let t=e,n="";const i=e.match(/\s+([1-9][0-9]*w|[0-9]+(?:\.[0-9]+)?x)$/);if(i){t=t.slice(0,-i[0].length);const e=+i[1].slice(0,-1),r=i[1].slice(-1);1===e&&"x"===r||(n=" "+e+r)}try{const e=await r.minifyURLs(t);return("string"==typeof e?e:t)+n}catch(e){return r.log&&r.log(e),t+n}}))).join(", ");else if(function(e,t){if("meta"!==e)return!1;for(let e=0,n=t.length;e<n;e++)if("name"===t[e].name&&"viewport"===t[e].value)return!0}(e,i)&&"content"===t)n=n.replace(/\s+/g,"").replace(/[0-9]+\.[0-9]+/g,function(e){return(+e).toString()});else{if(function(e,t){if("meta"!==e)return!1;for(let e=0,n=t.length;e<n;e++)if("http-equiv"===t[e].name.toLowerCase()&&"content-security-policy"===t[e].value.toLowerCase())return!0}(e,i)&&"content"===t.toLowerCase())return LE(n);if(r.customAttrCollapse&&r.customAttrCollapse.test(t))n=NE(n.replace(/ ?[\n\r]+ ?/g,"").replace(/\s{2,}/g,r.conservativeCollapse?" ":""));else if("script"===e&&"type"===t)n=NE(n.replace(/\s*;\s*/g,";"));else{if(function(e,t,n){return"media"===n&&(ZE(e,t,"stylesheet")||QE(e,t))}(e,i,t))return n=NE(n),r.minifyCSS(n,"media");if("iframe"===e&&"srcdoc"===t)return function(e){return Boolean(e.collapseWhitespace||e.removeComments||e.removeOptionalTags||e.minifyJS!==Dv||e.minifyCSS!==wv||e.minifyURLs!==Dv)}(r)?o(n,r,!0):n}}}return n}function ev(e){return"/* clean-css ignore:start */"+e+"/* clean-css ignore:end */"}function tv(e,t){switch(t){case"inline":return"*{"+e+"}";case"media":return"@media "+e+"{a{top:0}}";default:return e}}const nv=new Set(["html","head","body","colgroup","tbody"]),rv=new Set(["html","head","body","li","dt","dd","p","rb","rt","rtc","rp","optgroup","option","colgroup","caption","thead","tbody","tfoot","tr","td","th"]),iv=new Set(["meta","link","script","style","template","noscript"]),ov=new Set(["dt","dd"]),av=new Set(["address","article","aside","blockquote","details","dialog","div","dl","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","main","menu","nav","ol","p","pre","search","section","table","ul"]),sv=new Set(["a","audio","del","ins","map","noscript","video"]),uv=new Set(["rb","rt","rtc","rp"]),cv=new Set(["rb","rtc"]),lv=new Set(["option","optgroup"]),fv=new Set(["tbody","tfoot"]),pv=new Set(["thead","tbody","tfoot"]),dv=new Set(["td","th"]),hv=new Set(["html","head","body"]),Av=new Set(["html","body"]),mv=new Set(["head","colgroup","caption"]),gv=new Set(["dt","thead"]),_v=new Set(["a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","bgsound","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","command","content","data","datalist","dd","del","details","dfn","dialog","dir","div","dl","dt","element","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","image","img","input","ins","isindex","kbd","keygen","label","legend","li","link","listing","main","map","mark","marquee","menu","menuitem","meta","meter","multicol","nav","nobr","noembed","noframes","noscript","object","ol","optgroup","option","output","p","param","picture","plaintext","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr","xmp"]);const Ev=new RegExp("^(?:class|id|style|title|lang|dir|on(?:focus|blur|change|click|dblclick|mouse(?:down|up|over|move|out)|key(?:press|down|up)))$");function vv(e,t){for(let n=t.length-1;n>=0;n--)if(t[n].name===e)return!0;return!1}function bv(e){return!/^(?:script|style|pre|textarea)$/.test(e)}function yv(e){return!/^(?:pre|textarea)$/.test(e)}async function Sv(e,t,n,r){const i=r.name(e.name);let o=e.value;if(r.decodeEntities&&o&&(o=Jl(o,Ql.Strict)),!(r.removeRedundantAttributes&&function(e,t,n,r){return n=n?NE(n.toLowerCase()):"","script"===e&&"language"===t&&"javascript"===n||"form"===e&&"method"===t&&"get"===n||"input"===e&&"type"===t&&"text"===n||"script"===e&&"charset"===t&&!HE(r,"src")||"a"===e&&"name"===t&&HE(r,"id")||"area"===e&&"shape"===t&&"rect"===n}(n,i,o,t)||r.removeScriptTypeAttributes&&"script"===n&&"type"===i&&YE(o)&&!function(e=""){return e=NE(e.split(/;/,2)[0]).toLowerCase(),zE.has(e)}(o)||r.removeStyleLinkTypeAttributes&&("style"===n||"link"===n)&&"type"===i&&XE(o)||(o&&(o=await $E(n,i,o,r,t,Iv)),r.removeEmptyAttributes&&function(e,t,n,r){return!(n&&!/^\s*$/.test(n))&&("function"==typeof r.removeEmptyAttributes?r.removeEmptyAttributes(t,e):"input"===e&&"value"===t||Ev.test(t))}(n,i,o,r))))return r.decodeEntities&&o&&(o=o.replace(/&(#?[0-9a-zA-Z]+;)/g,"&amp;$1")),{attr:e,name:i,value:o}}function Cv(e,t,n,r,i){const o=e.name;let a=e.value;const s=e.attr;let u,c,l=s.quote;if(void 0===a||n.removeAttributeQuotes&&!~a.indexOf(i)&&/^[^ \t\n\f\r"'`=<>]+$/.test(a))c=!r||t||/\/$/.test(a)?a+" ":a;else{if(!n.preventAttributesEscaping){if(void 0===n.quoteCharacter){l=(a.match(/'/g)||[]).length<(a.match(/"/g)||[]).length?"'":'"'}else l="'"===n.quoteCharacter?"'":'"';a='"'===l?a.replace(/"/g,"&#34;"):a.replace(/'/g,"&#39;")}c=l+a+l,r||n.removeTagWhitespace||(c+=" ")}return void 0===a||n.collapseBooleanAttributes&&function(e,t){return jE.has(e)||"draggable"===e&&!qE.has(t)}(o.toLowerCase(),a.toLowerCase())?(u=o,r||(u+=" ")):u=o+s.customAssign+c,s.customOpen+u+s.customClose}function Dv(e){return e}function wv(e){return Promise.resolve(e)}const Rv=e=>{const t={name:function(e){return e.toLowerCase()},canCollapseWhitespace:bv,canTrimWhitespace:yv,html5:!0,ignoreCustomComments:[/^!/,/^\s*#/],ignoreCustomFragments:[/<%[\s\S]*?%>/,/<\?[\s\S]*?\?>/],includeAutoGeneratedTags:!0,log:Dv,minifyCSS:wv,minifyJS:Dv,minifyURLs:Dv};return Object.keys(e).forEach(function(n){const r=e[n];if("caseSensitive"===n)r&&(t.name=Dv);else if("log"===n)"function"==typeof r&&(t.log=r);else if("minifyCSS"===n&&"function"!=typeof r){if(!r)return;const e="object"==typeof r?r:{};t.minifyCSS=async function(n,r){const i=tv(n=await hE(n,/(url\s*\(\s*)(?:"([^"]*)"|'([^']*)'|([^\s)]+))(\s*\))/gi,async function(e,n,r,i,o,a){const s=null!=r?'"':null!=i?"'":"",u=r??i??o??"";try{const e=await t.minifyURLs(u);return n+s+("string"==typeof e?e:u)+s+a}catch(n){return t.log&&t.log(n),e}}),r);return new Promise(o=>{new Ll(e).minify(i,(e,i)=>{i.errors.length>0&&(i.errors.forEach(t.log),o(n));const a=function(e,t){let n;switch(t){case"inline":n=e.match(/^\*\{([\s\S]*)\}$/);break;case"media":n=e.match(/^@media ([\s\S]*?)\s*{[\s\S]*}$/)}return n?n[1]:e}(i.styles,r);o(a)})})}}else if("minifyJS"===n&&"function"!=typeof r){if(!r)return;const e="object"==typeof r?r:{};e.parse={...e.parse,bare_returns:!1},t.minifyJS=async function(n,r){const i=n.match(/^\s*<!--.*/),o=i?n.slice(i[0].length).replace(/\n\s*-->\s*$/,""):n;e.parse.bare_returns=r;try{const t=await async function(e,t){const n=dE(e,t);let r,i;do{i=n.next(await r),r=i.value}while(!i.done);return i.value}(o,e);return t.code.replace(/;$/,"")}catch(e){return t.log(e),n}}}else if("minifyURLs"===n&&"function"!=typeof r){if(!r)return;let e=r;"string"==typeof r?e={site:r}:"object"!=typeof r&&(e={}),t.minifyURLs=function(n){try{return Hf.relate(n,e)}catch(e){return t.log(e),n}}}else t[n]=r}),t};function Tv(e){let t;do{t=Math.random().toString(36).replace(/^0\.[0-9]*/,"")}while(~e.indexOf(t));return t}const Ov=new Set(["script","style"]);async function Iv(e,t,n){if(t.maxInputLength&&e.length>t.maxInputLength)throw new Error(`Input length (${e.length}) exceeds maximum allowed length (${t.maxInputLength})`);t.collapseWhitespace&&(e=PE(e,t,!0,!0));const r=[];let i,o,a="",s="",u=[];const c=[],l=[];let f="",p="";const d=[],h=[];let A,m,g;const _=t.inlineCustomElements??[],E=(Array.isArray(_)?_:Array.from(_)).map(e=>t.name(e)),v=new Set([...VE,...E]),b=new Set([...UE,...E]);e=e.replace(/<!-- htmlmin:ignore -->([\s\S]*?)<!-- htmlmin:ignore -->/g,function(n,r){if(!A){A=Tv(e);const n=new RegExp("^"+A+"([0-9]+)$");t.ignoreCustomComments?t.ignoreCustomComments=t.ignoreCustomComments.slice():t.ignoreCustomComments=[],t.ignoreCustomComments.push(n)}const i="\x3c!--"+A+d.length+"--\x3e";return d.push(r),i});const y=t.ignoreCustomFragments.map(function(e){return e.source});if(y.length){for(let e=0;e<y.length;e++)if(/[*+]/.test(y[e])){t.log("Warning: Custom fragment contains unlimited quantifiers (* or +) which may cause ReDoS vulnerability");break}const n=t.customFragmentQuantifierLimit||200,r=`\\s{0,${n}}`,i=new RegExp(r+"(?:"+y.join("|")+"){1,"+n+"}"+r,"g");e=e.replace(i,function(n){var r;m||(m=Tv(e),g=new RegExp("(\\s*)"+m+"([0-9]+)"+m+"(\\s*)","g"),t.minifyCSS&&(t.minifyCSS=(r=t.minifyCSS,function(e,t){e=e.replace(g,function(e,t,n){const r=h[+n];return r[1]+m+n+m+r[2]});const n=[];return(new Ll).minify(tv(e,t)).warnings.forEach(function(t){const r=g.exec(t);if(r){const t=m+r[2]+m;e=e.replace(t,ev(t)),n.push(t)}}),r(e,t).then(e=>(n.forEach(function(t){e=e.replace(ev(t),t)}),e))})),t.minifyJS&&(t.minifyJS=function(e){return function(t,n){return e(t.replace(g,function(e,t,n){const r=h[+n];return r[1]+m+n+m+r[2]}),n)}}(t.minifyJS)));const i=m+h.length+m;return h.push(/^(\s*)[\s\S]*?(\s*)$/.exec(n)),"\t"+i+"\t"})}function S(e,n){return t.canTrimWhitespace(e,n,yv)}function C(){let e=r.length-1;for(;e>0&&!/^<[^/!]/.test(r[e]);)e--;r.length=Math.max(0,e)}function D(){let e=r.length-1;for(;e>0&&!/^<\//.test(r[e]);)e--;r.length=Math.max(0,e)}function w(e,n){for(let i=null;e>=0&&S(i);e--){const o=r[e],a=o.match(/^<\/([\w:-]+)>$/);if(a)i=a[1];else if(/>$/.test(o)||(r[e]=GE(o,null,n,t,b,v)))break}}function R(e){let t=r.length-1;if(r.length>1){const e=r[r.length-1];/^(?:<!|$)/.test(e)&&-1===e.indexOf(A)&&t--}w(t,e)}(t.sortAttributes&&"function"!=typeof t.sortAttributes||t.sortClassName&&"function"!=typeof t.sortClassName)&&await async function(e,t,n,r){const i=t.sortAttributes&&Object.create(null),o=t.sortClassName&&new ME;function a(e){return e.map(function(e){return t.name(e.name)})}function s(e,t){return!t||-1===e.indexOf(t)}function u(e){return s(e,n)&&s(e,r)}const c=t.log;if(t.log=Dv,t.sortAttributes=!1,t.sortClassName=!1,await async function e(n){let r,s;const c=new xE(n,{start:function(e,n){i&&(i[e]||(i[e]=new ME),i[e].add(a(n).filter(u)));for(let i=0,a=n.length;i<a;i++){const a=n[i];o&&a.value&&"class"===t.name(a.name)?o.add(NE(a.value).split(/[ \t\n\f\r]+/).filter(u)):t.processScripts&&"type"===a.name.toLowerCase()&&(r=e,s=a.value)}},end:function(){r=""},chars:async function(n){t.processScripts&&Ov.has(r)&&t.processScripts.indexOf(s)>-1&&await e(n)}});await c.parse()}(await Iv(e,t)),t.log=c,i){const e=Object.create(null);for(const t in i)e[t]=i[t].createSorter();t.sortAttributes=function(t,n){const r=e[t];if(r){const e=Object.create(null),t=a(n);t.forEach(function(t,r){(e[t]||(e[t]=[])).push(n[r])}),r.sort(t).forEach(function(t,r){n[r]=e[t].shift()})}}}if(o){const e=o.createSorter();t.sortClassName=function(t){return e.sort(t.split(/[ \n\f\r]+/)).join(" ")}}}(e,t,A,m);const T=new xE(e,{partialMarkup:n,continueOnParseError:t.continueOnParseError,customAttrAssign:t.customAttrAssign,customAttrSurround:t.customAttrSurround,html5:t.html5,start:async function(e,n,d,h,A){"svg"===e.toLowerCase()&&((t=Object.create(t)).caseSensitive=!0,t.keepClosingSlash=!0,t.name=Dv),e=t.name(e),s=e,i=e,v.has(e)||(a=""),o=!1,u=n;let g=t.removeOptionalTags;if(g){const t=_v.has(e);t&&function(e,t){switch(e){case"html":case"head":return!0;case"body":return!iv.has(t);case"colgroup":return"col"===t;case"tbody":return"tr"===t}return!1}(f,e)&&C(),f="",t&&function(e,t){switch(e){case"html":case"head":case"body":case"colgroup":case"caption":return!0;case"li":case"optgroup":case"tr":return t===e;case"dt":case"dd":return ov.has(t);case"p":return av.has(t);case"rb":case"rt":case"rp":return uv.has(t);case"rtc":return cv.has(t);case"option":return lv.has(t);case"thead":case"tbody":return fv.has(t);case"tfoot":return"tbody"===t;case"td":case"th":return dv.has(t)}return!1}(p,e)&&(D(),g=!function(e,t){switch(t){case"colgroup":return"colgroup"===e;case"tbody":return pv.has(e)}return!1}(p,e)),p=""}t.collapseWhitespace&&(c.length||R(e),d||(S(e,n)&&!c.length||c.push(e),function(e,n){return t.canCollapseWhitespace(e,n,bv)}(e,n)&&!l.length||l.push(e)));const _="<"+e,E=h&&t.keepClosingSlash;r.push(_),t.sortAttributes&&t.sortAttributes(e,n);const b=[];for(let r=n.length,i=!0;--r>=0;){const o=await Sv(n[r],n,e,t);o&&(b.unshift(Cv(o,E,t,i,m)),i=!1)}b.length>0?(r.push(" "),r.push.apply(r,b)):g&&nv.has(e)&&(f=e),r.push(r.pop()+(E?"/":"")+">"),A&&!t.includeAutoGeneratedTags&&(C(),f="")},end:function(e,n,u){"svg"===e.toLowerCase()&&(t=Object.getPrototypeOf(t)),e=t.name(e),t.collapseWhitespace&&(c.length?e===c[c.length-1]&&c.pop():R("/"+e),l.length&&e===l[l.length-1]&&l.pop());let d=!1;e===s&&(s="",d=!o),t.removeOptionalTags&&(d&&hv.has(f)&&C(),f="",!_v.has(e)||!p||gv.has(p)||"p"===p&&sv.has(e)||D(),p=rv.has(e)?e:""),t.removeEmptyElements&&d&&function(e,t){switch(e){case"textarea":return!1;case"audio":case"script":case"video":if(vv("src",t))return!1;break;case"iframe":if(vv("src",t)||vv("srcdoc",t))return!1;break;case"object":if(vv("data",t))return!1;break;case"applet":if(vv("code",t))return!1}return!0}(e,n)?(C(),f="",p=""):(u&&!t.includeAutoGeneratedTags?p="":r.push("</"+e+">"),i="/"+e,b.has(e)?d&&(a+="|"):a="")},chars:async function(e,n,d){if(n=""===n?"comment":n,d=""===d?"comment":d,t.decodeEntities&&e&&!Ov.has(s)&&(e=function(e,t=Ql.Legacy){return Jl(e,t)}(e)),t.collapseWhitespace){if(!c.length){if("comment"===n){const o=r[r.length-1];if(-1===o.indexOf(A)&&(o||(n=i),r.length>1&&(!o||!t.conservativeCollapse&&/ $/.test(a)))){const t=r.length-2;r[t]=r[t].replace(/\s+$/,function(t){return e=t+e,""})}}if(n)if("/nobr"===n||"wbr"===n){if(/^\s/.test(e)){let e=r.length-1;for(;e>0&&0!==r[e].lastIndexOf("<"+n);)e--;w(e-1,"br")}}else v.has("/"===n.charAt(0)?n.slice(1):n)&&(e=PE(e,t,/(?:^|\s)$/.test(a)));!(e=n||d?GE(e,n,d,t,b,v):PE(e,t,!0,!0))&&/\s$/.test(a)&&n&&"/"===n.charAt(0)&&w(r.length-1,d)}l.length||"html"===d||n&&d||(e=PE(e,t,!1,!1,!0))}t.processScripts&&Ov.has(s)&&(e=await async function(e,t,n){for(let r=0,i=n.length;r<i;r++)if("type"===n[r].name.toLowerCase()&&t.processScripts.indexOf(n[r].value)>-1)return await Iv(e,t);return e}(e,t,u)),function(e,t){if("script"!==e)return!1;for(let e=0,n=t.length;e<n;e++)if("type"===t[e].name.toLowerCase())return YE(t[e].value);return!0}(s,u)&&(e=await t.minifyJS(e)),QE(s,u)&&(e=await t.minifyCSS(e)),t.removeOptionalTags&&e&&(("html"===f||"body"===f&&!/^\s/.test(e))&&C(),f="",(Av.has(p)||mv.has(p)&&!/^\s/.test(e))&&D(),/^\s+$/.test(e)&&t.collapseWhitespace&&!t.conservativeCollapse||(p="")),i=/^\s*$/.test(e)?n:"comment",t.decodeEntities&&e&&!Ov.has(s)&&(e=e.replace(/&((?: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,"&amp$1").replace(/</g,"&lt;")),g&&t.collapseWhitespace&&c.length&&(e=e.replace(g,function(e,t,n){return h[+n][0]})),a+=e,e&&(o=!0),r.push(e)},comment:async function(e,n){const i=n?"<!":"\x3c!--",o=n?">":"--\x3e";e=function(e){return/^\[if\s[^\]]+]|\[endif]$/.test(e)}(e)?i+await async function(e,t){return t.processConditionalComments?await hE(e,/^(\[if\s[^\]]+]>)([\s\S]*?)(<!\[endif])$/,async function(e,n,r,i){return n+await Iv(r,t,!0)+i}):e}(e,t)+o:t.removeComments?function(e,t){for(let n=0,r=t.ignoreCustomComments.length;n<r;n++)if(t.ignoreCustomComments[n].test(e))return!0;return!1}(e,t)?"\x3c!--"+e+"--\x3e":"":i+e+o,t.removeOptionalTags&&e&&(f="",p=""),r.push(e)},doctype:function(e){r.push(t.useShortDoctype?"<!doctype"+(t.removeTagWhitespace?"":" ")+"html>":LE(e))}});return await T.parse(),t.removeOptionalTags&&(hv.has(f)&&C(),p&&!gv.has(p)&&D()),t.collapseWhitespace&&R("br"),function(e,t,n,r){let i;const o=t.maxLineLength,a=t.noNewlinesBeforeTagClose;if(o){let t="";const s=[];for(;e.length;){const i=t.length,u=e[0].indexOf("\n"),c=Boolean(e[0].match(yE)),l=a&&c;u<0?t+=r(n(e.shift())):(t+=r(n(e[0].slice(0,u))),e[0]=e[0].slice(u+1)),i>0&&t.length>o&&!l?(s.push(t.slice(0,i)),t=t.slice(i)):u>=0&&(s.push(t),t="")}t&&s.push(t),i=s.join("\n")}else i=r(n(e.join("")));return t.collapseWhitespace?PE(i,t,!0,!0):i}(r,t,g?function(e){return e.replace(g,function(e,n,r,i){let o=h[+r][0];return t.collapseWhitespace?("\t"!==n&&(o=n+o),"\t"!==i&&(o+=i),PE(o,{preserveLineBreaks:t.preserveLineBreaks,conservativeCollapse:!t.trimCustomFragments},/^[ \n\r\t\f]/.test(o),/[ \n\r\t\f]$/.test(o))):o})}:Dv,A?function(e){return e.replace(new RegExp("\x3c!--"+A+"([0-9]+)--\x3e","g"),function(e,t){return d[+t]})}:Dv)}const kv=async function(e,t){const n=Date.now();t=Rv(t||{});const r=await Iv(e,t);return t.log("minified in: "+(Date.now()-n)+"ms"),r};var Fv={minify:kv};e.default=Fv,e.minify=kv,Object.defineProperty(e,"__esModule",{value:!0})});
package/package.json CHANGED
@@ -7,22 +7,22 @@
7
7
  "dependencies": {
8
8
  "change-case": "^4.1.2",
9
9
  "clean-css": "~5.3.3",
10
- "commander": "^14.0.0",
10
+ "commander": "^14.0.1",
11
11
  "entities": "^7.0.0",
12
12
  "relateurl": "^0.2.7",
13
13
  "terser": "^5.44.0"
14
14
  },
15
- "description": "Highly configurable, well-tested, JavaScript-based HTML minifier.",
15
+ "description": "Highly configurable, well-tested, JavaScript-based HTML minifier",
16
16
  "devDependencies": {
17
- "@commitlint/cli": "^19.8.1",
18
- "@eslint/js": "^9.35.0",
19
- "@jest/globals": "^30.1.2",
17
+ "@commitlint/cli": "^20.1.0",
18
+ "@eslint/js": "^9.36.0",
19
+ "@jest/globals": "^30.2.0",
20
20
  "@rollup/plugin-commonjs": "^28.0.6",
21
21
  "@rollup/plugin-json": "^6.1.0",
22
22
  "@rollup/plugin-node-resolve": "^16.0.1",
23
23
  "@rollup/plugin-terser": "^0.4.4",
24
- "eslint": "^9.35.0",
25
- "jest": "^30.1.3",
24
+ "eslint": "^9.36.0",
25
+ "jest": "^30.2.0",
26
26
  "rollup": "^4.50.0",
27
27
  "rollup-plugin-polyfill-node": "^0.13.0",
28
28
  "vite": "^7.1.5"
@@ -85,5 +85,5 @@
85
85
  "test:watch": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --watch"
86
86
  },
87
87
  "type": "module",
88
- "version": "2.1.4"
88
+ "version": "2.1.6"
89
89
  }
@@ -59,9 +59,9 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll) {
59
59
  }
60
60
 
61
61
  // Non-empty elements that will maintain whitespace around them
62
- const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
62
+ const inlineElementsToKeepWhitespaceAround = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
63
63
  // Non-empty elements that will maintain whitespace within them
64
- const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 'rp', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
64
+ const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
65
65
  // Elements that will always maintain whitespace around them
66
66
  const inlineElementsToKeepWhitespace = new Set(['comment', 'img', 'input', 'wbr']);
67
67
 
@@ -414,19 +414,18 @@ async function processScript(text, options, currentAttrs) {
414
414
  return text;
415
415
  }
416
416
 
417
- // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
418
- // with the following deviations:
417
+ // Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags with the following extensions:
419
418
  // - retain <body> if followed by <noscript>
420
- // - </rb>, </rt>, </rtc>, </rp>, and </tfoot> follow https://www.w3.org/TR/html5/syntax.html#optional-tags
419
+ // - <rb>, <rt>, <rtc>, <rp> follow HTML Ruby Markup Extensions draft (https://www.w3.org/TR/html-ruby-extensions/)
421
420
  // - retain all tags which are adjacent to non-standard HTML tags
422
421
  const optionalStartTags = new Set(['html', 'head', 'body', 'colgroup', 'tbody']);
423
422
  const optionalEndTags = new Set(['html', 'head', 'body', 'li', 'dt', 'dd', 'p', 'rb', 'rt', 'rtc', 'rp', 'optgroup', 'option', 'colgroup', 'caption', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th']);
424
423
  const headerTags = new Set(['meta', 'link', 'script', 'style', 'template', 'noscript']);
425
424
  const descriptionTags = new Set(['dt', 'dd']);
426
- const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul']);
425
+ const pBlockTags = new Set(['address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'search', 'section', 'table', 'ul']);
427
426
  const pInlineTags = new Set(['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video']);
428
- const rubyTags = new Set(['rb', 'rt', 'rtc', 'rp']);
429
- const rtcTag = new Set(['rb', 'rtc', 'rp']);
427
+ const rubyEndTagOmission = new Set(['rb', 'rt', 'rtc', 'rp']); // </rb>, </rt>, </rp> can be omitted if followed by <rb>, <rt>, <rtc>, or <rp>
428
+ const rubyRtcEndTagOmission = new Set(['rb', 'rtc']); // </rtc> can be omitted if followed by <rb> or <rtc> (not <rt> or <rp>)
430
429
  const optionTag = new Set(['option', 'optgroup']);
431
430
  const tableContentTags = new Set(['tbody', 'tfoot']);
432
431
  const tableSectionTags = new Set(['thead', 'tbody', 'tfoot']);
@@ -482,9 +481,9 @@ function canRemovePrecedingTag(optionalEndTag, tag) {
482
481
  case 'rb':
483
482
  case 'rt':
484
483
  case 'rp':
485
- return rubyTags.has(tag);
484
+ return rubyEndTagOmission.has(tag);
486
485
  case 'rtc':
487
- return rtcTag.has(tag);
486
+ return rubyRtcEndTagOmission.has(tag);
488
487
  case 'option':
489
488
  return optionTag.has(tag);
490
489
  case 'thead':
@@ -1094,7 +1093,7 @@ async function minifyHTML(value, options, partialMarkup) {
1094
1093
  let optional = options.removeOptionalTags;
1095
1094
  if (optional) {
1096
1095
  const htmlTag = htmlTags.has(tag);
1097
- // <html> may be omitted if first thing inside is not comment
1096
+ // <html> may be omitted if first thing inside is not a comment
1098
1097
  // <head> may be omitted if first thing inside is an element
1099
1098
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
1100
1099
  // <colgroup> may be omitted if first thing inside is <col>
@@ -1113,7 +1112,7 @@ async function minifyHTML(value, options, partialMarkup) {
1113
1112
  optionalEndTag = '';
1114
1113
  }
1115
1114
 
1116
- // Set whitespace flags for nested tags (eg. <code> within a <pre>)
1115
+ // Set whitespace flags for nested tags (e.g., <code> within a <pre>)
1117
1116
  if (options.collapseWhitespace) {
1118
1117
  if (!stackNoTrimWhitespace.length) {
1119
1118
  squashTrailingWhitespace(tag);
@@ -1281,7 +1280,7 @@ async function minifyHTML(value, options, partialMarkup) {
1281
1280
  text = await options.minifyCSS(text);
1282
1281
  }
1283
1282
  if (options.removeOptionalTags && text) {
1284
- // <html> may be omitted if first thing inside is not comment
1283
+ // <html> may be omitted if first thing inside is not a comment
1285
1284
  // <body> may be omitted if first thing inside is not space, comment, <meta>, <link>, <script>, <style> or <template>
1286
1285
  if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(text))) {
1287
1286
  removeStartTag();
@@ -1292,7 +1291,10 @@ async function minifyHTML(value, options, partialMarkup) {
1292
1291
  if (compactTags.has(optionalEndTag) || (looseTags.has(optionalEndTag) && !/^\s/.test(text))) {
1293
1292
  removeEndTag();
1294
1293
  }
1295
- optionalEndTag = '';
1294
+ // Don’t reset optionalEndTag if text is only whitespace and will be collapsed (not conservatively)
1295
+ if (!/^\s+$/.test(text) || !options.collapseWhitespace || options.conservativeCollapse) {
1296
+ optionalEndTag = '';
1297
+ }
1296
1298
  }
1297
1299
  charsPrevTag = /^\s*$/.test(text) ? prevTag : 'comment';
1298
1300
  if (options.decodeEntities && text && !specialContentTags.has(currentTag)) {
@@ -1346,7 +1348,7 @@ async function minifyHTML(value, options, partialMarkup) {
1346
1348
  await parser.parse();
1347
1349
 
1348
1350
  if (options.removeOptionalTags) {
1349
- // <html> may be omitted if first thing inside is not comment
1351
+ // <html> may be omitted if first thing inside is not a comment
1350
1352
  // <head> or <body> may be omitted if empty
1351
1353
  if (topLevelTags.has(optionalStartTag)) {
1352
1354
  removeStartTag();
package/src/htmlparser.js CHANGED
@@ -122,7 +122,7 @@ export class HTMLParser {
122
122
  if (!lastTag || !special.has(lastTag)) {
123
123
  let textEnd = html.indexOf('<');
124
124
  if (textEnd === 0) {
125
- // Comment:
125
+ // Comment
126
126
  if (/^<!--/.test(html)) {
127
127
  const commentEnd = html.indexOf('-->');
128
128
 
@@ -150,7 +150,7 @@ export class HTMLParser {
150
150
  }
151
151
  }
152
152
 
153
- // Doctype:
153
+ // Doctype
154
154
  const doctypeMatch = html.match(doctype);
155
155
  if (doctypeMatch) {
156
156
  if (handler.doctype) {
@@ -161,7 +161,7 @@ export class HTMLParser {
161
161
  continue;
162
162
  }
163
163
 
164
- // End tag:
164
+ // End tag
165
165
  const endTagMatch = html.match(endTag);
166
166
  if (endTagMatch) {
167
167
  html = html.substring(endTagMatch[0].length);
@@ -170,7 +170,7 @@ export class HTMLParser {
170
170
  continue;
171
171
  }
172
172
 
173
- // Start tag:
173
+ // Start tag
174
174
  const startTagMatch = parseStartTag(html);
175
175
  if (startTagMatch) {
176
176
  html = startTagMatch.rest;
@@ -263,11 +263,41 @@ export class HTMLParser {
263
263
  }
264
264
  }
265
265
 
266
- async function closeIfFound(tagName) {
267
- if (findTag(tagName) >= 0) {
268
- await parseEndTag('', tagName);
266
+ function findTagInCurrentTable(tagName) {
267
+ let pos;
268
+ const needle = tagName.toLowerCase();
269
+ for (pos = stack.length - 1; pos >= 0; pos--) {
270
+ const currentTag = stack[pos].tag.toLowerCase();
271
+ if (currentTag === needle) {
272
+ return pos;
273
+ }
274
+ // Stop searching if we hit a table boundary
275
+ if (currentTag === 'table') {
276
+ break;
277
+ }
278
+ }
279
+ return -1;
280
+ }
281
+
282
+ async function parseEndTagAt(pos) {
283
+ // Close all open elements up to pos (mirrors parseEndTag’s core branch)
284
+ for (let i = stack.length - 1; i >= pos; i--) {
285
+ if (handler.end) {
286
+ await handler.end(stack[i].tag, stack[i].attrs, true);
287
+ }
288
+ }
289
+ stack.length = pos;
290
+ lastTag = pos && stack[pos - 1].tag;
291
+ }
292
+
293
+ async function closeIfFoundInCurrentTable(tagName) {
294
+ const pos = findTagInCurrentTable(tagName);
295
+ if (pos >= 0) {
296
+ // Close at the specific index to avoid re-searching
297
+ await parseEndTagAt(pos);
269
298
  return true;
270
299
  }
300
+ return false;
271
301
  }
272
302
 
273
303
  async function handleStartTag(match) {
@@ -278,10 +308,15 @@ export class HTMLParser {
278
308
  if (lastTag === 'p' && nonPhrasing.has(tagName)) {
279
309
  await parseEndTag('', lastTag);
280
310
  } else if (tagName === 'tbody') {
281
- await closeIfFound('thead');
311
+ await closeIfFoundInCurrentTable('thead');
282
312
  } else if (tagName === 'tfoot') {
283
- if (!await closeIfFound('tbody')) {
284
- await closeIfFound('thead');
313
+ if (!await closeIfFoundInCurrentTable('tbody')) {
314
+ await closeIfFoundInCurrentTable('thead');
315
+ }
316
+ } else if (tagName === 'thead') {
317
+ // If a `tbody` or `tfoot` is open in the current table, close it
318
+ if (!await closeIfFoundInCurrentTable('tbody')) {
319
+ await closeIfFoundInCurrentTable('tfoot');
285
320
  }
286
321
  }
287
322
  if (tagName === 'col' && findTag('colgroup') < 0) {