Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rude-ads-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"unpic": patch
---

fix(storyblok): update splitfilters in storyblok provider to not split on colons inside focal() filter
26 changes: 23 additions & 3 deletions src/providers/storyblok.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ const OLD_BASE_URL =

Deno.test("Storyblok Image CDN - extract", async (t) => {
await t.step("should extract operations from new URL format", () => {
const url = `${NEW_BASE_URL}/m/400x300/filters:format(webp)`;
const url = `${NEW_BASE_URL}/m/400x300/filters:format(webp):focal(150x100:250x200)`;
const result = extract(url);
assertEquals(result, {
src: NEW_BASE_URL,
operations: {
width: 400,
height: 300,
format: "webp",
filters: {},
filters: {
focal: "150x100:250x200",
},
},
});
});
Expand Down Expand Up @@ -47,6 +49,8 @@ Deno.test("Storyblok Image CDN - extract", async (t) => {
},
});
});


});

Deno.test("Storyblok Image CDN - generate", async (t) => {
Expand Down Expand Up @@ -88,6 +92,17 @@ Deno.test("Storyblok Image CDN - generate", async (t) => {
});
assertEquals(result, `${NEW_BASE_URL}/m/-400x-300`);
});

await t.step("should generate URL with focal point", () => {
const result = generate(NEW_BASE_URL, {
width: 400,
height: 300,
filters:{
focal: "150x150:250x250"
}
});
assertEquals(result, `${NEW_BASE_URL}/m/400x300/filters:focal(150x150:250x250)`);
});
});

Deno.test("Storyblok Image CDN - transform", async (t) => {
Expand All @@ -96,10 +111,13 @@ Deno.test("Storyblok Image CDN - transform", async (t) => {
width: 500,
height: 400,
format: "webp",
filters:{
focal: "150x150:250x250"
}
});
assertEquals(
result,
`${NEW_BASE_URL}/m/500x400/filters:format(webp)`,
`${NEW_BASE_URL}/m/500x400/filters:focal(150x150:250x250):format(webp)`,
);
});

Expand All @@ -124,3 +142,5 @@ Deno.test("Storyblok Image CDN - transform", async (t) => {
);
});
});


6 changes: 5 additions & 1 deletion src/providers/storyblok.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const storyBlokAssets =
const storyBlokImg2 =
/^(?<modifiers>\/(?<crop>\d+x\d+:\d+x\d+)?\/?(?<resize>(?<flipx>\-)?(?<width>\d+)x(?<flipy>\-)?(?<height>\d+))?\/?(filters\:(?<filters>[^\/]+))?\/?)?(?<id>\/f\/.+)$/;

// This regex selects every colon(:) that is not inside parentheses. So that focal(150x150:250x250) is not split into two filters.
const filterSplitterRegex = /:(?![^(]*\))/;

export interface StoryblokOperations extends Operations {
crop?: string;
filters?: Record<string, string>;
Expand All @@ -27,8 +30,9 @@ const splitFilters = (filters: string): Record<string, string> => {
if (!filters) {
return {};
}

return Object.fromEntries(
filters.split(":").map((filter) => {
filters.split(filterSplitterRegex).map((filter) => {
if (!filter) return [];
const [key, value] = filter.split("(");
return [key, value.replace(")", "")];
Expand Down