html-minifier-next 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/cli.js +1 -1
- package/dist/htmlminifier.cjs +1929 -0
- package/dist/htmlminifier.esm.bundle.js +62020 -0
- package/dist/htmlminifier.umd.bundle.js +62031 -0
- package/dist/htmlminifier.umd.bundle.min.js +9 -0
- package/package.json +3 -2
- package/src/htmlminifier.js +41 -13
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"commander": "^14.0.0",
|
|
11
11
|
"entities": "^6.0.1",
|
|
12
12
|
"relateurl": "^0.2.7",
|
|
13
|
-
"terser": "^5.
|
|
13
|
+
"terser": "^5.44.0"
|
|
14
14
|
},
|
|
15
15
|
"description": "Highly configurable, well-tested, JavaScript-based HTML minifier.",
|
|
16
16
|
"devDependencies": {
|
|
@@ -82,11 +82,12 @@
|
|
|
82
82
|
"build:docs": "vite build --base /html-minifier-next/ --outDir build",
|
|
83
83
|
"deploy": "npm run build && npm run build:docs",
|
|
84
84
|
"lint": "eslint .",
|
|
85
|
+
"prepack": "npm run build",
|
|
85
86
|
"prepare": "husky",
|
|
86
87
|
"serve": "npm run build && vite",
|
|
87
88
|
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest",
|
|
88
89
|
"test:watch": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --watch"
|
|
89
90
|
},
|
|
90
91
|
"type": "module",
|
|
91
|
-
"version": "1.4.
|
|
92
|
+
"version": "1.4.3"
|
|
92
93
|
}
|
package/src/htmlminifier.js
CHANGED
|
@@ -240,14 +240,15 @@ function isNumberTypeAttribute(attrName, tag) {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
function isLinkType(tag, attrs, value) {
|
|
243
|
-
if (tag !== 'link')
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return true;
|
|
243
|
+
if (tag !== 'link') return false;
|
|
244
|
+
const needle = String(value).toLowerCase();
|
|
245
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
246
|
+
if (attrs[i].name.toLowerCase() === 'rel') {
|
|
247
|
+
const tokens = String(attrs[i].value).toLowerCase().split(/\s+/);
|
|
248
|
+
if (tokens.includes(needle)) return true;
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
+
return false;
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
function isMediaQuery(tag, attrs, attrName) {
|
|
@@ -274,7 +275,16 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
|
|
|
274
275
|
return attrValue;
|
|
275
276
|
} else if (isUriTypeAttribute(attrName, tag)) {
|
|
276
277
|
attrValue = trimWhitespace(attrValue);
|
|
277
|
-
|
|
278
|
+
if (isLinkType(tag, attrs, 'canonical')) {
|
|
279
|
+
return attrValue;
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
const out = await options.minifyURLs(attrValue);
|
|
283
|
+
return typeof out === 'string' ? out : attrValue;
|
|
284
|
+
} catch (err) {
|
|
285
|
+
options.log && options.log(err);
|
|
286
|
+
return attrValue;
|
|
287
|
+
}
|
|
278
288
|
} else if (isNumberTypeAttribute(attrName, tag)) {
|
|
279
289
|
return trimWhitespace(attrValue);
|
|
280
290
|
} else if (attrName === 'style') {
|
|
@@ -288,7 +298,7 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
|
|
|
288
298
|
return attrValue;
|
|
289
299
|
} else if (isSrcset(attrName, tag)) {
|
|
290
300
|
// https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset
|
|
291
|
-
attrValue = trimWhitespace(attrValue).split(/\s+,\s*|\s*,\s+/).map(function (candidate) {
|
|
301
|
+
attrValue = (await Promise.all(trimWhitespace(attrValue).split(/\s+,\s*|\s*,\s+/).map(async function (candidate) {
|
|
292
302
|
let url = candidate;
|
|
293
303
|
let descriptor = '';
|
|
294
304
|
const match = candidate.match(/\s+([1-9][0-9]*w|[0-9]+(?:\.[0-9]+)?x)$/);
|
|
@@ -300,8 +310,14 @@ async function cleanAttributeValue(tag, attrName, attrValue, options, attrs, min
|
|
|
300
310
|
descriptor = ' ' + num + suffix;
|
|
301
311
|
}
|
|
302
312
|
}
|
|
303
|
-
|
|
304
|
-
|
|
313
|
+
try {
|
|
314
|
+
const out = await options.minifyURLs(url);
|
|
315
|
+
return (typeof out === 'string' ? out : url) + descriptor;
|
|
316
|
+
} catch (err) {
|
|
317
|
+
options.log && options.log(err);
|
|
318
|
+
return url + descriptor;
|
|
319
|
+
}
|
|
320
|
+
}))).join(', ');
|
|
305
321
|
} else if (isMetaViewport(tag, attrs) && attrName === 'content') {
|
|
306
322
|
attrValue = attrValue.replace(/\s+/g, '').replace(/[0-9]+\.[0-9]+/g, function (numString) {
|
|
307
323
|
// "0.90000" -> "0.9"
|
|
@@ -692,9 +708,21 @@ const processOptions = (inputOptions) => {
|
|
|
692
708
|
const cleanCssOptions = typeof option === 'object' ? option : {};
|
|
693
709
|
|
|
694
710
|
options.minifyCSS = async function (text, type) {
|
|
695
|
-
text =
|
|
696
|
-
|
|
697
|
-
|
|
711
|
+
text = await replaceAsync(
|
|
712
|
+
text,
|
|
713
|
+
/(url\s*\(\s*)(?:"([^"]*)"|'([^']*)'|([^\s)]+))(\s*\))/ig,
|
|
714
|
+
async function (match, prefix, dq, sq, unq, suffix) {
|
|
715
|
+
const quote = dq != null ? '"' : (sq != null ? "'" : '');
|
|
716
|
+
const url = dq ?? sq ?? unq ?? '';
|
|
717
|
+
try {
|
|
718
|
+
const out = await options.minifyURLs(url);
|
|
719
|
+
return prefix + quote + (typeof out === 'string' ? out : url) + quote + suffix;
|
|
720
|
+
} catch (err) {
|
|
721
|
+
options.log && options.log(err);
|
|
722
|
+
return match;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
);
|
|
698
726
|
|
|
699
727
|
const inputCSS = wrapCSS(text, type);
|
|
700
728
|
|