From 1e134baf26befddc0659e9f504be263b97f192ec Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Feb 2026 15:59:23 +0000 Subject: [PATCH 1/2] fix(cloudflare_images): handle named variants without =undefined issue When a Cloudflare Images URL contains a named variant like "public" instead of actual transformations, the parser would create { public: undefined } which resulted in malformed URLs like "public=undefined,w=640,h=480". Now we check if the captured transformations segment contains "=" to distinguish actual transformations from named variants. Named variants are ignored and treated as having no transformations. Fixes #188 https://claude.ai/code/session_016hmKJGc8B6LARXgAscYWNt --- src/providers/cloudflare_images.test.ts | 72 +++++++++++++++++++++++++ src/providers/cloudflare_images.ts | 4 +- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/providers/cloudflare_images.test.ts b/src/providers/cloudflare_images.test.ts index 61abc49..54a3efd 100644 --- a/src/providers/cloudflare_images.test.ts +++ b/src/providers/cloudflare_images.test.ts @@ -56,6 +56,42 @@ Deno.test("Cloudflare Images CDN - extract", async (t) => { const result = extract("https://example.com/image.jpg"); assertEquals(result, null); }); + + await t.step( + "should handle URL with named variant (no transformations)", + () => { + const result = extract( + "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123/public", + ); + assertEquals(result, { + src: "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123", + operations: {}, + options: { + host: "imagedelivery.net", + accountHash: "5LGXGUnHU18h6ehN_xjpXQ", + imageId: "abc123", + }, + }); + }, + ); + + await t.step( + "should handle URL without any transformations or variant", + () => { + const result = extract( + "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123", + ); + assertEquals(result, { + src: "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123", + operations: {}, + options: { + host: "imagedelivery.net", + accountHash: "5LGXGUnHU18h6ehN_xjpXQ", + imageId: "abc123", + }, + }); + }, + ); }); Deno.test("Cloudflare Images CDN - generate", async (t) => { @@ -154,4 +190,40 @@ Deno.test("Cloudflare Images CDN - transform", async (t) => { ); } }); + + await t.step( + "should transform URL with named variant without =undefined issue", + () => { + const result = transform( + "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123/public", + { + width: 640, + height: 480, + }, + {}, + ); + assertEqualIgnoringQueryOrder( + result, + "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123/w=640,h=480,fit=cover", + ); + }, + ); + + await t.step( + "should transform URL without variant", + () => { + const result = transform( + "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123", + { + width: 640, + height: 480, + }, + {}, + ); + assertEqualIgnoringQueryOrder( + result, + "https://imagedelivery.net/5LGXGUnHU18h6ehN_xjpXQ/abc123/w=640,h=480,fit=cover", + ); + }, + ); }); diff --git a/src/providers/cloudflare_images.ts b/src/providers/cloudflare_images.ts index 0d72091..97360d3 100644 --- a/src/providers/cloudflare_images.ts +++ b/src/providers/cloudflare_images.ts @@ -98,7 +98,9 @@ export const extract: URLExtractor< } const { host, accountHash, imageId, transformations } = matches[0].groups; - const operations = operationsParser(transformations || ""); + // Named variants (like "public") don't contain "=", only actual transformations do + const hasTransformations = transformations?.includes("="); + const operations = operationsParser(hasTransformations ? transformations : ""); const options = { host, accountHash, imageId }; From e1a747c449deb5558ac827e1dd9e1d270b514687 Mon Sep 17 00:00:00 2001 From: ascorbic <213306+ascorbic@users.noreply.github.com> Date: Mon, 2 Feb 2026 16:06:13 +0000 Subject: [PATCH 2/2] chore: format --- src/providers/cloudflare.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/cloudflare.ts b/src/providers/cloudflare.ts index a6ce00a..773a23f 100644 --- a/src/providers/cloudflare.ts +++ b/src/providers/cloudflare.ts @@ -114,7 +114,7 @@ export const generate: URLGenerator<"cloudflare"> = ( ) => { const modifiers = operationsGenerator(operations); const url = toUrl(options?.domain ? `https://${options.domain}` : "/"); - + const srcStr = src.toString(); let pathSuffix = stripLeadingSlash(srcStr);