diff --git a/src/asset-inliner.mjs b/src/asset-inliner.mjs index 15fa2d9..c8e31f3 100644 --- a/src/asset-inliner.mjs +++ b/src/asset-inliner.mjs @@ -260,6 +260,7 @@ export class AssetInliner { async rewriteMediaAttributes(tag, baseUrl) { let output = tag; const tagName = getTagName(output); + const hadSrc = !!getAttribute(output, "src"); for (const attr of ["src", "poster", "data"]) { const value = getAttribute(output, attr); if (!value) { @@ -274,6 +275,12 @@ export class AssetInliner { } const srcset = getAttribute(output, "srcset"); if (srcset) { + if (tagName === "source") { + return removeAttribute(output, "srcset"); + } + if (tagName === "img" && hadSrc) { + return removeAttribute(output, "srcset"); + } const rewritten = await this.inlineSrcset(srcset, baseUrl); output = setAttribute(output, "srcset", rewritten); } diff --git a/test/asset-inliner.test.mjs b/test/asset-inliner.test.mjs index 2237c4c..841db32 100644 --- a/test/asset-inliner.test.mjs +++ b/test/asset-inliner.test.mjs @@ -103,6 +103,29 @@ test("removes image preload srcsets when the link has no href", async () => { assert.deepEqual(findExternalAssetRefs(output), []); }); +test("drops responsive image candidates after snapshot src is available", 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(` + + + + + `, "https://example.com/article"); + + assert.deepEqual(fetched, ["https://example.com/selected.jpg"]); + assert.doesNotMatch(output, /srcset=/); + assert.deepEqual(findExternalAssetRefs(output), []); +}); + test("asset inliner skips URLs blocked by the filter hook", async () => { const blocked = []; const inliner = new AssetInliner({