html-minifier-next 4.11.0 → 4.12.0
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 +16 -16
- package/cli.js +177 -68
- package/dist/htmlminifier.cjs +206 -35
- package/dist/htmlminifier.esm.bundle.js +206 -35
- package/dist/types/htmlminifier.d.ts.map +1 -1
- package/dist/types/htmlparser.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/htmlminifier.js +195 -28
- package/src/htmlparser.js +11 -7
|
@@ -5234,7 +5234,7 @@ const preCompiledStackedTags = {
|
|
|
5234
5234
|
// Cache for compiled attribute regexes per handler configuration
|
|
5235
5235
|
const attrRegexCache = new WeakMap();
|
|
5236
5236
|
|
|
5237
|
-
function
|
|
5237
|
+
function buildAttrRegex(handler) {
|
|
5238
5238
|
let pattern = singleAttrIdentifier.source +
|
|
5239
5239
|
'(?:\\s*(' + joinSingleAttrAssigns(handler) + ')' +
|
|
5240
5240
|
'[ \\t\\n\\f\\r]*(?:' + singleAttrValues.join('|') + '))?';
|
|
@@ -5253,6 +5253,14 @@ function attrForHandler(handler) {
|
|
|
5253
5253
|
return new RegExp('^\\s*' + pattern);
|
|
5254
5254
|
}
|
|
5255
5255
|
|
|
5256
|
+
function getAttrRegexForHandler(handler) {
|
|
5257
|
+
let cached = attrRegexCache.get(handler);
|
|
5258
|
+
if (cached) return cached;
|
|
5259
|
+
const compiled = buildAttrRegex(handler);
|
|
5260
|
+
attrRegexCache.set(handler, compiled);
|
|
5261
|
+
return compiled;
|
|
5262
|
+
}
|
|
5263
|
+
|
|
5256
5264
|
function joinSingleAttrAssigns(handler) {
|
|
5257
5265
|
return singleAttrAssigns.concat(
|
|
5258
5266
|
handler.customAttrAssign || []
|
|
@@ -5276,12 +5284,8 @@ class HTMLParser {
|
|
|
5276
5284
|
const fullLength = fullHtml.length;
|
|
5277
5285
|
|
|
5278
5286
|
const stack = []; let lastTag;
|
|
5279
|
-
// Use cached attribute regex
|
|
5280
|
-
|
|
5281
|
-
if (!attribute) {
|
|
5282
|
-
attribute = attrForHandler(handler);
|
|
5283
|
-
attrRegexCache.set(handler, attribute);
|
|
5284
|
-
}
|
|
5287
|
+
// Use cached attribute regex for this handler configuration
|
|
5288
|
+
const attribute = getAttrRegexForHandler(handler);
|
|
5285
5289
|
let prevTag = undefined, nextTag = undefined;
|
|
5286
5290
|
|
|
5287
5291
|
// Index-based parsing
|
|
@@ -6405,7 +6409,7 @@ const cssMinifyCache = new LRU(200);
|
|
|
6405
6409
|
|
|
6406
6410
|
const trimWhitespace = str => {
|
|
6407
6411
|
if (!str) return str;
|
|
6408
|
-
// Fast path:
|
|
6412
|
+
// Fast path: If no whitespace at start or end, return early
|
|
6409
6413
|
if (!/^[ \n\r\t\f]/.test(str) && !/[ \n\r\t\f]$/.test(str)) {
|
|
6410
6414
|
return str;
|
|
6411
6415
|
}
|
|
@@ -6414,7 +6418,7 @@ const trimWhitespace = str => {
|
|
|
6414
6418
|
|
|
6415
6419
|
function collapseWhitespaceAll(str) {
|
|
6416
6420
|
if (!str) return str;
|
|
6417
|
-
// Fast path:
|
|
6421
|
+
// Fast path: If there are no common whitespace characters, return early
|
|
6418
6422
|
if (!/[ \n\r\t\f\xA0]/.test(str)) {
|
|
6419
6423
|
return str;
|
|
6420
6424
|
}
|
|
@@ -6782,7 +6786,7 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
|
|
|
6782
6786
|
return options.minifyCSS(attrValue, 'media');
|
|
6783
6787
|
} else if (tag === 'iframe' && attrName === 'srcdoc') {
|
|
6784
6788
|
// Recursively minify HTML content within srcdoc attribute
|
|
6785
|
-
// Fast-path:
|
|
6789
|
+
// Fast-path: Skip if nothing would change
|
|
6786
6790
|
if (!shouldMinifyInnerHTML(options)) {
|
|
6787
6791
|
return attrValue;
|
|
6788
6792
|
}
|
|
@@ -7169,7 +7173,7 @@ async function normalizeAttr(attr, attrs, tag, options) {
|
|
|
7169
7173
|
let attrValue = attr.value;
|
|
7170
7174
|
|
|
7171
7175
|
if (options.decodeEntities && attrValue) {
|
|
7172
|
-
// Fast path:
|
|
7176
|
+
// Fast path: Only decode when entities are present
|
|
7173
7177
|
if (attrValue.indexOf('&') !== -1) {
|
|
7174
7178
|
attrValue = decodeHTMLStrict(attrValue);
|
|
7175
7179
|
}
|
|
@@ -7214,7 +7218,9 @@ function buildAttr(normalized, hasUnarySlash, options, isLast, uidAttr) {
|
|
|
7214
7218
|
|
|
7215
7219
|
if (typeof attrValue !== 'undefined' && (!options.removeAttributeQuotes ||
|
|
7216
7220
|
~attrValue.indexOf(uidAttr) || !canRemoveAttributeQuotes(attrValue))) {
|
|
7221
|
+
// Determine the appropriate quote character
|
|
7217
7222
|
if (!options.preventAttributesEscaping) {
|
|
7223
|
+
// Normal mode: choose quotes and escape
|
|
7218
7224
|
if (typeof options.quoteCharacter === 'undefined') {
|
|
7219
7225
|
// Count quotes in a single pass instead of two regex operations
|
|
7220
7226
|
let apos = 0, quot = 0;
|
|
@@ -7231,6 +7237,50 @@ function buildAttr(normalized, hasUnarySlash, options, isLast, uidAttr) {
|
|
|
7231
7237
|
} else {
|
|
7232
7238
|
attrValue = attrValue.replace(/'/g, ''');
|
|
7233
7239
|
}
|
|
7240
|
+
} else {
|
|
7241
|
+
// `preventAttributesEscaping` mode: choose safe quotes but don’t escape
|
|
7242
|
+
// EXCEPT when both quote types are present—then escape to prevent invalid HTML
|
|
7243
|
+
const hasDoubleQuote = attrValue.indexOf('"') !== -1;
|
|
7244
|
+
const hasSingleQuote = attrValue.indexOf("'") !== -1;
|
|
7245
|
+
|
|
7246
|
+
if (hasDoubleQuote && hasSingleQuote) {
|
|
7247
|
+
// Both quote types present: `preventAttributesEscaping` is ignored to ensure valid HTML
|
|
7248
|
+
// Choose the quote type with fewer occurrences and escape the other
|
|
7249
|
+
if (typeof options.quoteCharacter === 'undefined') {
|
|
7250
|
+
let apos = 0, quot = 0;
|
|
7251
|
+
for (let i = 0; i < attrValue.length; i++) {
|
|
7252
|
+
if (attrValue[i] === "'") apos++;
|
|
7253
|
+
else if (attrValue[i] === '"') quot++;
|
|
7254
|
+
}
|
|
7255
|
+
attrQuote = apos < quot ? '\'' : '"';
|
|
7256
|
+
} else {
|
|
7257
|
+
attrQuote = options.quoteCharacter === '\'' ? '\'' : '"';
|
|
7258
|
+
}
|
|
7259
|
+
if (attrQuote === '"') {
|
|
7260
|
+
attrValue = attrValue.replace(/"/g, '"');
|
|
7261
|
+
} else {
|
|
7262
|
+
attrValue = attrValue.replace(/'/g, ''');
|
|
7263
|
+
}
|
|
7264
|
+
} else if (typeof options.quoteCharacter === 'undefined') {
|
|
7265
|
+
// Single or no quote type: Choose safe quote delimiter
|
|
7266
|
+
if (attrQuote === '"' && hasDoubleQuote && !hasSingleQuote) {
|
|
7267
|
+
attrQuote = "'";
|
|
7268
|
+
} else if (attrQuote === "'" && hasSingleQuote && !hasDoubleQuote) {
|
|
7269
|
+
attrQuote = '"';
|
|
7270
|
+
} else if (attrQuote !== '"' && attrQuote !== "'" && attrQuote !== '') {
|
|
7271
|
+
// `attrQuote` is invalid/undefined (not `"`, `'`, or empty string)
|
|
7272
|
+
// Set a safe default based on the value’s content
|
|
7273
|
+
if (hasSingleQuote && !hasDoubleQuote) {
|
|
7274
|
+
attrQuote = '"'; // Value has single quotes, use double quotes as delimiter
|
|
7275
|
+
} else if (hasDoubleQuote && !hasSingleQuote) {
|
|
7276
|
+
attrQuote = "'"; // Value has double quotes, use single quotes as delimiter
|
|
7277
|
+
} else {
|
|
7278
|
+
attrQuote = '"'; // No quotes in value, default to double quotes
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
} else {
|
|
7282
|
+
attrQuote = options.quoteCharacter === '\'' ? '\'' : '"';
|
|
7283
|
+
}
|
|
7234
7284
|
}
|
|
7235
7285
|
emittedAttrValue = attrQuote + attrValue + attrQuote;
|
|
7236
7286
|
if (!isLast && !options.removeTagWhitespace) {
|
|
@@ -7323,7 +7373,7 @@ const processOptions = (inputOptions) => {
|
|
|
7323
7373
|
const lightningCssOptions = typeof option === 'object' ? option : {};
|
|
7324
7374
|
|
|
7325
7375
|
options.minifyCSS = async function (text, type) {
|
|
7326
|
-
// Fast path:
|
|
7376
|
+
// Fast path: Nothing to minify
|
|
7327
7377
|
if (!text || !text.trim()) {
|
|
7328
7378
|
return text;
|
|
7329
7379
|
}
|
|
@@ -7415,7 +7465,7 @@ const processOptions = (inputOptions) => {
|
|
|
7415
7465
|
|
|
7416
7466
|
let jsKey;
|
|
7417
7467
|
try {
|
|
7418
|
-
// Fast path:
|
|
7468
|
+
// Fast path: Avoid invoking Terser for empty/whitespace-only content
|
|
7419
7469
|
if (!code || !code.trim()) {
|
|
7420
7470
|
return '';
|
|
7421
7471
|
}
|
|
@@ -7467,9 +7517,18 @@ const processOptions = (inputOptions) => {
|
|
|
7467
7517
|
relateUrlOptions = {};
|
|
7468
7518
|
}
|
|
7469
7519
|
|
|
7520
|
+
// Cache RelateURL instance for reuse (expensive to create)
|
|
7521
|
+
const relateUrlInstance = new RelateURL(relateUrlOptions.site || '', relateUrlOptions);
|
|
7522
|
+
|
|
7470
7523
|
options.minifyURLs = function (text) {
|
|
7524
|
+
// Fast-path: Skip if text doesn’t look like a URL that needs processing
|
|
7525
|
+
// Only process if contains URL-like characters (`/`, `:`, `#`, `?`) or spaces that need encoding
|
|
7526
|
+
if (!/[/:?#\s]/.test(text)) {
|
|
7527
|
+
return text;
|
|
7528
|
+
}
|
|
7529
|
+
|
|
7471
7530
|
try {
|
|
7472
|
-
return
|
|
7531
|
+
return relateUrlInstance.relate(text);
|
|
7473
7532
|
} catch (err) {
|
|
7474
7533
|
if (!options.continueOnMinifyError) {
|
|
7475
7534
|
throw err;
|
|
@@ -7495,7 +7554,7 @@ function uniqueId(value) {
|
|
|
7495
7554
|
|
|
7496
7555
|
const specialContentTags = new Set(['script', 'style']);
|
|
7497
7556
|
|
|
7498
|
-
async function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
7557
|
+
async function createSortFns(value, options, uidIgnore, uidAttr, ignoredMarkupChunks) {
|
|
7499
7558
|
const attrChains = options.sortAttributes && Object.create(null);
|
|
7500
7559
|
const classChain = options.sortClassName && new TokenChain();
|
|
7501
7560
|
|
|
@@ -7509,10 +7568,20 @@ async function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
7509
7568
|
return !uid || token.indexOf(uid) === -1;
|
|
7510
7569
|
}
|
|
7511
7570
|
|
|
7512
|
-
function
|
|
7571
|
+
function shouldKeepToken(token) {
|
|
7572
|
+
// Filter out any HTML comment tokens (UID placeholders)
|
|
7573
|
+
// These are temporary markers created by `htmlmin:ignore` and `ignoreCustomFragments`
|
|
7574
|
+
if (token.startsWith('<!--') && token.endsWith('-->')) {
|
|
7575
|
+
return false;
|
|
7576
|
+
}
|
|
7513
7577
|
return shouldSkipUID(token, uidIgnore) && shouldSkipUID(token, uidAttr);
|
|
7514
7578
|
}
|
|
7515
7579
|
|
|
7580
|
+
// Pre-compile regex patterns for reuse (performance optimization)
|
|
7581
|
+
// These must be declared before scan() since scan uses them
|
|
7582
|
+
const whitespaceSplitPatternScan = /[ \t\n\f\r]+/;
|
|
7583
|
+
const whitespaceSplitPatternSort = /[ \n\f\r]+/;
|
|
7584
|
+
|
|
7516
7585
|
async function scan(input) {
|
|
7517
7586
|
let currentTag, currentType;
|
|
7518
7587
|
const parser = new HTMLParser(input, {
|
|
@@ -7521,12 +7590,14 @@ async function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
7521
7590
|
if (!attrChains[tag]) {
|
|
7522
7591
|
attrChains[tag] = new TokenChain();
|
|
7523
7592
|
}
|
|
7524
|
-
|
|
7593
|
+
const attrNamesList = attrNames(attrs).filter(shouldKeepToken);
|
|
7594
|
+
attrChains[tag].add(attrNamesList);
|
|
7525
7595
|
}
|
|
7526
7596
|
for (let i = 0, len = attrs.length; i < len; i++) {
|
|
7527
7597
|
const attr = attrs[i];
|
|
7528
7598
|
if (classChain && attr.value && options.name(attr.name) === 'class') {
|
|
7529
|
-
|
|
7599
|
+
const classes = trimWhitespace(attr.value).split(whitespaceSplitPatternScan).filter(shouldKeepToken);
|
|
7600
|
+
classChain.add(classes);
|
|
7530
7601
|
} else if (options.processScripts && attr.name.toLowerCase() === 'type') {
|
|
7531
7602
|
currentTag = tag;
|
|
7532
7603
|
currentType = attr.value;
|
|
@@ -7546,19 +7617,84 @@ async function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
7546
7617
|
}
|
|
7547
7618
|
},
|
|
7548
7619
|
// We never need `nextTag` information in this scan
|
|
7549
|
-
wantsNextTag: false
|
|
7620
|
+
wantsNextTag: false,
|
|
7621
|
+
// Continue on parse errors during analysis pass
|
|
7622
|
+
continueOnParseError: options.continueOnParseError
|
|
7550
7623
|
});
|
|
7551
7624
|
|
|
7552
|
-
|
|
7625
|
+
try {
|
|
7626
|
+
await parser.parse();
|
|
7627
|
+
} catch (err) {
|
|
7628
|
+
// If parsing fails during analysis pass, just skip it—we’ll still have
|
|
7629
|
+
// partial frequency data from what we could parse
|
|
7630
|
+
if (!options.continueOnParseError) {
|
|
7631
|
+
throw err;
|
|
7632
|
+
}
|
|
7633
|
+
}
|
|
7553
7634
|
}
|
|
7554
7635
|
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
const
|
|
7560
|
-
|
|
7561
|
-
|
|
7636
|
+
// For the first pass, create a copy of options and disable aggressive minification.
|
|
7637
|
+
// Keep attribute transformations (like `removeStyleLinkTypeAttributes`) for accurate analysis.
|
|
7638
|
+
// This is safe because `createSortFns` is called before custom fragment UID markers (uidAttr) are added.
|
|
7639
|
+
// Note: `htmlmin:ignore` UID markers (uidIgnore) already exist and are expanded for analysis.
|
|
7640
|
+
const firstPassOptions = Object.assign({}, options, {
|
|
7641
|
+
// Disable sorting for the analysis pass
|
|
7642
|
+
sortAttributes: false,
|
|
7643
|
+
sortClassName: false,
|
|
7644
|
+
// Disable aggressive minification that doesn’t affect attribute analysis
|
|
7645
|
+
collapseWhitespace: false,
|
|
7646
|
+
removeAttributeQuotes: false,
|
|
7647
|
+
removeTagWhitespace: false,
|
|
7648
|
+
decodeEntities: false,
|
|
7649
|
+
processScripts: false,
|
|
7650
|
+
// Keep `ignoreCustomFragments` to handle template syntax correctly
|
|
7651
|
+
// This is safe because `createSortFns` is now called before UID markers are added
|
|
7652
|
+
// Continue on parse errors during analysis (e.g., template syntax)
|
|
7653
|
+
continueOnParseError: true,
|
|
7654
|
+
log: identity
|
|
7655
|
+
});
|
|
7656
|
+
|
|
7657
|
+
// Temporarily enable `continueOnParseError` for the `scan()` function call below.
|
|
7658
|
+
// Note: `firstPassOptions` already has `continueOnParseError: true` for the minifyHTML call.
|
|
7659
|
+
const originalContinueOnParseError = options.continueOnParseError;
|
|
7660
|
+
options.continueOnParseError = true;
|
|
7661
|
+
|
|
7662
|
+
// Pre-compile regex patterns for UID replacement and custom fragments
|
|
7663
|
+
const uidReplacePattern = uidIgnore && ignoredMarkupChunks
|
|
7664
|
+
? new RegExp('<!--' + uidIgnore + '(\\d+)-->', 'g')
|
|
7665
|
+
: null;
|
|
7666
|
+
const customFragmentPattern = options.ignoreCustomFragments && options.ignoreCustomFragments.length > 0
|
|
7667
|
+
? new RegExp('(' + options.ignoreCustomFragments.map(re => re.source).join('|') + ')', 'g')
|
|
7668
|
+
: null;
|
|
7669
|
+
|
|
7670
|
+
try {
|
|
7671
|
+
// Expand UID tokens back to original content for frequency analysis
|
|
7672
|
+
let expandedValue = value;
|
|
7673
|
+
if (uidReplacePattern) {
|
|
7674
|
+
expandedValue = value.replace(uidReplacePattern, function (match, index) {
|
|
7675
|
+
return ignoredMarkupChunks[+index] || '';
|
|
7676
|
+
});
|
|
7677
|
+
// Reset `lastIndex` for pattern reuse
|
|
7678
|
+
uidReplacePattern.lastIndex = 0;
|
|
7679
|
+
}
|
|
7680
|
+
|
|
7681
|
+
// First pass minification applies attribute transformations
|
|
7682
|
+
// like removeStyleLinkTypeAttributes for accurate frequency analysis
|
|
7683
|
+
const firstPassOutput = await minifyHTML(expandedValue, firstPassOptions);
|
|
7684
|
+
|
|
7685
|
+
// For frequency analysis, we need to remove custom fragments temporarily
|
|
7686
|
+
// because HTML comments in opening tags prevent proper attribute parsing.
|
|
7687
|
+
// We remove them with a space to preserve attribute boundaries.
|
|
7688
|
+
let scanValue = firstPassOutput;
|
|
7689
|
+
if (customFragmentPattern) {
|
|
7690
|
+
scanValue = firstPassOutput.replace(customFragmentPattern, ' ');
|
|
7691
|
+
}
|
|
7692
|
+
|
|
7693
|
+
await scan(scanValue);
|
|
7694
|
+
} finally {
|
|
7695
|
+
// Restore original option
|
|
7696
|
+
options.continueOnParseError = originalContinueOnParseError;
|
|
7697
|
+
}
|
|
7562
7698
|
if (attrChains) {
|
|
7563
7699
|
const attrSorters = Object.create(null);
|
|
7564
7700
|
for (const tag in attrChains) {
|
|
@@ -7572,7 +7708,8 @@ async function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
7572
7708
|
names.forEach(function (name, index) {
|
|
7573
7709
|
(attrMap[name] || (attrMap[name] = [])).push(attrs[index]);
|
|
7574
7710
|
});
|
|
7575
|
-
sorter.sort(names)
|
|
7711
|
+
const sorted = sorter.sort(names);
|
|
7712
|
+
sorted.forEach(function (name, index) {
|
|
7576
7713
|
attrs[index] = attrMap[name].shift();
|
|
7577
7714
|
});
|
|
7578
7715
|
}
|
|
@@ -7580,8 +7717,40 @@ async function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
7580
7717
|
}
|
|
7581
7718
|
if (classChain) {
|
|
7582
7719
|
const sorter = classChain.createSorter();
|
|
7720
|
+
// Memoize `sortClassName` results—class lists often repeat in templates
|
|
7721
|
+
const classNameCache = new LRU(200);
|
|
7722
|
+
|
|
7583
7723
|
options.sortClassName = function (value) {
|
|
7584
|
-
|
|
7724
|
+
// Fast path: Single class (no spaces) needs no sorting
|
|
7725
|
+
if (value.indexOf(' ') === -1) {
|
|
7726
|
+
return value;
|
|
7727
|
+
}
|
|
7728
|
+
|
|
7729
|
+
// Check cache first
|
|
7730
|
+
const cached = classNameCache.get(value);
|
|
7731
|
+
if (cached !== undefined) {
|
|
7732
|
+
return cached;
|
|
7733
|
+
}
|
|
7734
|
+
|
|
7735
|
+
// Expand UID tokens back to original content before sorting
|
|
7736
|
+
// Fast path: Skip if no HTML comments (UID markers) present
|
|
7737
|
+
let expandedValue = value;
|
|
7738
|
+
if (uidReplacePattern && value.indexOf('<!--') !== -1) {
|
|
7739
|
+
expandedValue = value.replace(uidReplacePattern, function (match, index) {
|
|
7740
|
+
return ignoredMarkupChunks[+index] || '';
|
|
7741
|
+
});
|
|
7742
|
+
// Reset `lastIndex` for pattern reuse
|
|
7743
|
+
uidReplacePattern.lastIndex = 0;
|
|
7744
|
+
}
|
|
7745
|
+
const classes = expandedValue.split(whitespaceSplitPatternSort).filter(function(cls) {
|
|
7746
|
+
return cls !== '';
|
|
7747
|
+
});
|
|
7748
|
+
const sorted = sorter.sort(classes);
|
|
7749
|
+
const result = sorted.join(' ');
|
|
7750
|
+
|
|
7751
|
+
// Cache the result
|
|
7752
|
+
classNameCache.set(value, result);
|
|
7753
|
+
return result;
|
|
7585
7754
|
};
|
|
7586
7755
|
}
|
|
7587
7756
|
}
|
|
@@ -7622,7 +7791,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
7622
7791
|
const customElementsInput = options.inlineCustomElements ?? [];
|
|
7623
7792
|
const customElementsArr = Array.isArray(customElementsInput) ? customElementsInput : Array.from(customElementsInput);
|
|
7624
7793
|
const normalizedCustomElements = customElementsArr.map(name => options.name(name));
|
|
7625
|
-
// Fast path:
|
|
7794
|
+
// Fast path: Reuse base Sets if no custom elements
|
|
7626
7795
|
const inlineTextSet = normalizedCustomElements.length
|
|
7627
7796
|
? new Set([...inlineElementsToKeepWhitespaceWithin, ...normalizedCustomElements])
|
|
7628
7797
|
: inlineElementsToKeepWhitespaceWithin;
|
|
@@ -7662,6 +7831,13 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
7662
7831
|
return token;
|
|
7663
7832
|
});
|
|
7664
7833
|
|
|
7834
|
+
// Create sort functions after `htmlmin:ignore` processing but before custom fragment UID markers
|
|
7835
|
+
// This allows proper frequency analysis with access to ignored content via UID tokens
|
|
7836
|
+
if ((options.sortAttributes && typeof options.sortAttributes !== 'function') ||
|
|
7837
|
+
(options.sortClassName && typeof options.sortClassName !== 'function')) {
|
|
7838
|
+
await createSortFns(value, options, uidIgnore, null, ignoredMarkupChunks);
|
|
7839
|
+
}
|
|
7840
|
+
|
|
7665
7841
|
const customFragments = options.ignoreCustomFragments.map(function (re) {
|
|
7666
7842
|
return re.source;
|
|
7667
7843
|
});
|
|
@@ -7720,11 +7896,6 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
7720
7896
|
});
|
|
7721
7897
|
}
|
|
7722
7898
|
|
|
7723
|
-
if ((options.sortAttributes && typeof options.sortAttributes !== 'function') ||
|
|
7724
|
-
(options.sortClassName && typeof options.sortClassName !== 'function')) {
|
|
7725
|
-
await createSortFns(value, options, uidIgnore, uidAttr);
|
|
7726
|
-
}
|
|
7727
|
-
|
|
7728
7899
|
function _canCollapseWhitespace(tag, attrs) {
|
|
7729
7900
|
return options.canCollapseWhitespace(tag, attrs, canCollapseWhitespace);
|
|
7730
7901
|
}
|
|
@@ -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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AA8CA,4BAAoE;
|
|
1
|
+
{"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AA8CA,4BAAoE;AA+EpE;IACE,qCAGC;IAFC,UAAgB;IAChB,aAAsB;IAGxB,uBAgeC;CACF"}
|
package/package.json
CHANGED