html-minifier-next 6.2.6 → 6.2.7
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/cli.js +1 -1
- package/dist/htmlminifier.cjs +36 -3
- package/dist/types/htmlminifier.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/htmlminifier.js +36 -3
package/cli.js
CHANGED
package/dist/htmlminifier.cjs
CHANGED
|
@@ -3891,6 +3891,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
3891
3891
|
let uidIgnorePlaceholderPattern;
|
|
3892
3892
|
let uidAttr;
|
|
3893
3893
|
let uidPattern;
|
|
3894
|
+
let uidAttrLeadingPattern;
|
|
3894
3895
|
// Create inline tags/text sets with custom elements
|
|
3895
3896
|
const customElementsInput = options.inlineCustomElements ?? [];
|
|
3896
3897
|
const customElementsArr = Array.isArray(customElementsInput) ? customElementsInput : Array.from(customElementsInput);
|
|
@@ -3982,6 +3983,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
3982
3983
|
if (!uidAttr) {
|
|
3983
3984
|
uidAttr = uniqueId(value);
|
|
3984
3985
|
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)' + uidAttr + '(\\s*)', 'g');
|
|
3986
|
+
uidAttrLeadingPattern = new RegExp('^\\s*' + uidAttr + '(\\d+)' + uidAttr);
|
|
3985
3987
|
|
|
3986
3988
|
if (options.minifyCSS) {
|
|
3987
3989
|
options.minifyCSS = (function (fn) {
|
|
@@ -4417,15 +4419,28 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
4417
4419
|
// Finalization phase (sync): Optional tag handling, entity re-encoding, buffer push
|
|
4418
4420
|
function charsFinalize(text) {
|
|
4419
4421
|
if (options.removeOptionalTags && text) {
|
|
4422
|
+
// UID-attr tokens are padded with `\t`, which would falsely look like leading whitespace;
|
|
4423
|
+
// resolve single-token text to its actual content for the space/comment checks below
|
|
4424
|
+
let effectiveText = text;
|
|
4425
|
+
if (uidAttrLeadingPattern && text.includes(uidAttr)) {
|
|
4426
|
+
const uidMatch = uidAttrLeadingPattern.exec(text);
|
|
4427
|
+
if (uidMatch) {
|
|
4428
|
+
const idx = +uidMatch[1];
|
|
4429
|
+
const chunks = idx < ignoredCustomMarkupChunks.length ? ignoredCustomMarkupChunks[idx] : null;
|
|
4430
|
+
if (chunks != null) {
|
|
4431
|
+
effectiveText = chunks[0];
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4420
4435
|
// `<html>` may be omitted if first thing inside is not a comment
|
|
4421
4436
|
// `<body>` may be omitted if first thing inside is not space, comment, `<meta>`, `<link>`, `<script>`, `<style>`, or `<template>`
|
|
4422
|
-
if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(
|
|
4437
|
+
if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(effectiveText))) {
|
|
4423
4438
|
removeStartTag();
|
|
4424
4439
|
}
|
|
4425
4440
|
optionalStartTag = '';
|
|
4426
4441
|
// `</html>` or `</body>` may be omitted if not followed by comment
|
|
4427
4442
|
// `</head>`, `</colgroup>`, or `</caption>` may be omitted if not followed by space or comment
|
|
4428
|
-
if (optionalEndTagEmitted && (compactElements.has(optionalEndTag) || (looseElements.has(optionalEndTag) && !/^\s/.test(
|
|
4443
|
+
if (optionalEndTagEmitted && (compactElements.has(optionalEndTag) || (looseElements.has(optionalEndTag) && !/^\s/.test(effectiveText)))) {
|
|
4429
4444
|
removeEndTag();
|
|
4430
4445
|
}
|
|
4431
4446
|
// Don’t reset `optionalEndTag` if text is only whitespace and will be collapsed (not conservatively)
|
|
@@ -4491,7 +4506,25 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
4491
4506
|
// Finalization phase (sync): Optional tag handling, `htmlmin:ignore` whitespace collapsing, buffer push
|
|
4492
4507
|
function commentFinalize(comment) {
|
|
4493
4508
|
if (options.removeOptionalTags && comment) {
|
|
4494
|
-
|
|
4509
|
+
if (uidIgnorePlaceholderPattern) {
|
|
4510
|
+
const match = uidIgnorePlaceholderPattern.exec(comment);
|
|
4511
|
+
if (match) {
|
|
4512
|
+
// UID placeholders represent real HTML content, not true HTML comments;
|
|
4513
|
+
// if there’s a pending optional end tag and the ignored content isn’t itself
|
|
4514
|
+
// a comment (which per the HTML spec prevents omission), resolve it now,
|
|
4515
|
+
// before the UID is pushed to the buffer
|
|
4516
|
+
const idx = +match[1];
|
|
4517
|
+
const content = idx < ignoredMarkupChunks.length ? ignoredMarkupChunks[idx] : null;
|
|
4518
|
+
if (optionalEndTag && optionalEndTagEmitted && content != null && !/^\s*<!--/.test(content)) {
|
|
4519
|
+
const firstTagMatch = content.match(/^\s*<([a-zA-Z][^\s/>]*)/);
|
|
4520
|
+
const firstTag = firstTagMatch ? options.name(firstTagMatch[1]) : '';
|
|
4521
|
+
if (canRemovePrecedingTag(optionalEndTag, firstTag)) {
|
|
4522
|
+
removeEndTag();
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
// Comments (real or placeholder) always suppress optional start tag omissions
|
|
4495
4528
|
optionalStartTag = '';
|
|
4496
4529
|
optionalEndTag = '';
|
|
4497
4530
|
optionalEndTagEmitted = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AA4yDO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAwB3B;;;;;;;;;;;;UA5hDS,MAAM;;;;;;;;;;;;;;;;;;mCAaA,MAAM,SAAS,aAAa,EAAE,yBAAyB,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;+BAM3F,MAAM,GAAG,IAAI,SAAS,aAAa,EAAE,GAAG,SAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6JtG,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2HA2BiF,MAAM,SAAS,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;iBASxG,QAAQ,GAAG,KAAK;gBAAgC,MAAM,WAAW,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;eAa/H,MAAM;gBAAY,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;;mBAiBzE,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDA+DF,MAAM,OAAO,MAAM,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA2EpC,MAAM,SAAS,aAAa,EAAE,KAAK,IAAI;;;;;;;;;wCAQrC,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;wBAtqBK,cAAc;0BAAd,cAAc;+BAAd,cAAc"}
|
package/package.json
CHANGED
package/src/htmlminifier.js
CHANGED
|
@@ -949,6 +949,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
949
949
|
let uidIgnorePlaceholderPattern;
|
|
950
950
|
let uidAttr;
|
|
951
951
|
let uidPattern;
|
|
952
|
+
let uidAttrLeadingPattern;
|
|
952
953
|
// Create inline tags/text sets with custom elements
|
|
953
954
|
const customElementsInput = options.inlineCustomElements ?? [];
|
|
954
955
|
const customElementsArr = Array.isArray(customElementsInput) ? customElementsInput : Array.from(customElementsInput);
|
|
@@ -1040,6 +1041,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1040
1041
|
if (!uidAttr) {
|
|
1041
1042
|
uidAttr = uniqueId(value);
|
|
1042
1043
|
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)' + uidAttr + '(\\s*)', 'g');
|
|
1044
|
+
uidAttrLeadingPattern = new RegExp('^\\s*' + uidAttr + '(\\d+)' + uidAttr);
|
|
1043
1045
|
|
|
1044
1046
|
if (options.minifyCSS) {
|
|
1045
1047
|
options.minifyCSS = (function (fn) {
|
|
@@ -1475,15 +1477,28 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1475
1477
|
// Finalization phase (sync): Optional tag handling, entity re-encoding, buffer push
|
|
1476
1478
|
function charsFinalize(text) {
|
|
1477
1479
|
if (options.removeOptionalTags && text) {
|
|
1480
|
+
// UID-attr tokens are padded with `\t`, which would falsely look like leading whitespace;
|
|
1481
|
+
// resolve single-token text to its actual content for the space/comment checks below
|
|
1482
|
+
let effectiveText = text;
|
|
1483
|
+
if (uidAttrLeadingPattern && text.includes(uidAttr)) {
|
|
1484
|
+
const uidMatch = uidAttrLeadingPattern.exec(text);
|
|
1485
|
+
if (uidMatch) {
|
|
1486
|
+
const idx = +uidMatch[1];
|
|
1487
|
+
const chunks = idx < ignoredCustomMarkupChunks.length ? ignoredCustomMarkupChunks[idx] : null;
|
|
1488
|
+
if (chunks != null) {
|
|
1489
|
+
effectiveText = chunks[0];
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1478
1493
|
// `<html>` may be omitted if first thing inside is not a comment
|
|
1479
1494
|
// `<body>` may be omitted if first thing inside is not space, comment, `<meta>`, `<link>`, `<script>`, `<style>`, or `<template>`
|
|
1480
|
-
if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(
|
|
1495
|
+
if (optionalStartTag === 'html' || (optionalStartTag === 'body' && !/^\s/.test(effectiveText))) {
|
|
1481
1496
|
removeStartTag();
|
|
1482
1497
|
}
|
|
1483
1498
|
optionalStartTag = '';
|
|
1484
1499
|
// `</html>` or `</body>` may be omitted if not followed by comment
|
|
1485
1500
|
// `</head>`, `</colgroup>`, or `</caption>` may be omitted if not followed by space or comment
|
|
1486
|
-
if (optionalEndTagEmitted && (compactElements.has(optionalEndTag) || (looseElements.has(optionalEndTag) && !/^\s/.test(
|
|
1501
|
+
if (optionalEndTagEmitted && (compactElements.has(optionalEndTag) || (looseElements.has(optionalEndTag) && !/^\s/.test(effectiveText)))) {
|
|
1487
1502
|
removeEndTag();
|
|
1488
1503
|
}
|
|
1489
1504
|
// Don’t reset `optionalEndTag` if text is only whitespace and will be collapsed (not conservatively)
|
|
@@ -1549,7 +1564,25 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1549
1564
|
// Finalization phase (sync): Optional tag handling, `htmlmin:ignore` whitespace collapsing, buffer push
|
|
1550
1565
|
function commentFinalize(comment) {
|
|
1551
1566
|
if (options.removeOptionalTags && comment) {
|
|
1552
|
-
|
|
1567
|
+
if (uidIgnorePlaceholderPattern) {
|
|
1568
|
+
const match = uidIgnorePlaceholderPattern.exec(comment);
|
|
1569
|
+
if (match) {
|
|
1570
|
+
// UID placeholders represent real HTML content, not true HTML comments;
|
|
1571
|
+
// if there’s a pending optional end tag and the ignored content isn’t itself
|
|
1572
|
+
// a comment (which per the HTML spec prevents omission), resolve it now,
|
|
1573
|
+
// before the UID is pushed to the buffer
|
|
1574
|
+
const idx = +match[1];
|
|
1575
|
+
const content = idx < ignoredMarkupChunks.length ? ignoredMarkupChunks[idx] : null;
|
|
1576
|
+
if (optionalEndTag && optionalEndTagEmitted && content != null && !/^\s*<!--/.test(content)) {
|
|
1577
|
+
const firstTagMatch = content.match(/^\s*<([a-zA-Z][^\s/>]*)/);
|
|
1578
|
+
const firstTag = firstTagMatch ? options.name(firstTagMatch[1]) : '';
|
|
1579
|
+
if (canRemovePrecedingTag(optionalEndTag, firstTag)) {
|
|
1580
|
+
removeEndTag();
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
// Comments (real or placeholder) always suppress optional start tag omissions
|
|
1553
1586
|
optionalStartTag = '';
|
|
1554
1587
|
optionalEndTag = '';
|
|
1555
1588
|
optionalEndTagEmitted = false;
|