Remove image preload refs without href

This commit is contained in:
2026-05-16 23:03:49 -07:00
parent 0ef0360fde
commit 2b28ada9d1
2 changed files with 31 additions and 3 deletions

View File

@@ -206,11 +206,11 @@ export class AssetInliner {
const rel = getAttribute(tag, "rel") || ""; const rel = getAttribute(tag, "rel") || "";
const href = getAttribute(tag, "href"); const href = getAttribute(tag, "href");
const asValue = getAttribute(tag, "as") || ""; const asValue = getAttribute(tag, "as") || "";
if (/\bstylesheet\b/i.test(rel)) {
if (!href) { if (!href) {
return tag; return tag;
} }
if (/\bstylesheet\b/i.test(rel)) {
const absolute = resolveUrl(href, baseUrl); const absolute = resolveUrl(href, baseUrl);
if (!absolute || absolute.startsWith("data:")) { if (!absolute || absolute.startsWith("data:")) {
return ""; return "";
@@ -237,12 +237,19 @@ export class AssetInliner {
} }
let output = tag; let output = tag;
if (/\bpreload\b/i.test(rel) && /^image$/i.test(asValue)) { if (/\bpreload\b/i.test(rel) && /^image$/i.test(asValue)) {
if (!href) {
return "";
}
const imageSrcset = getAttribute(output, "imagesrcset"); const imageSrcset = getAttribute(output, "imagesrcset");
if (imageSrcset) { if (imageSrcset) {
output = setAttribute(output, "imagesrcset", await this.inlineSrcset(imageSrcset, baseUrl)); output = setAttribute(output, "imagesrcset", await this.inlineSrcset(imageSrcset, baseUrl));
} }
} }
if (!href) {
return tag;
}
const dataUri = await this.toDataUri(href, baseUrl, linkResourceType(asValue)); const dataUri = await this.toDataUri(href, baseUrl, linkResourceType(asValue));
if (!dataUri) { if (!dataUri) {
return ""; return "";

View File

@@ -82,6 +82,27 @@ test("external asset reporting parses srcset-like attributes without splitting U
]); ]);
}); });
test("removes image preload srcsets when the link has no href", async () => {
const fetched = [];
const inliner = new AssetInliner();
inliner.fetchAsset = async (rawUrl) => {
fetched.push(rawUrl);
return {
bytes: Buffer.from("asset"),
contentType: "image/jpeg"
};
};
const output = await inliner.inlineHtml(`
<link rel="preload" as="image" imagesrcset="https://media.example/photos/id/master/w_120,c_limit/photo.jpg 120w, https://media.example/photos/id/master/w_240,c_limit/photo.jpg 240w">
`, "https://example.com/article");
assert.deepEqual(fetched, []);
assert.doesNotMatch(output, /https:\/\/media\.example/);
assert.doesNotMatch(output, /imagesrcset/);
assert.deepEqual(findExternalAssetRefs(output), []);
});
test("asset inliner skips URLs blocked by the filter hook", async () => { test("asset inliner skips URLs blocked by the filter hook", async () => {
const blocked = []; const blocked = [];
const inliner = new AssetInliner({ const inliner = new AssetInliner({