Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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/full-plums-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"unpic": patch
---

feat(ipx): improve ipx provider typing and test coverage
48 changes: 48 additions & 0 deletions src/providers/ipx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ Deno.test("ipx extract", async (t) => {
format: "webp",
});
});

await t.step("should extract crop with URL-encoded underscores", () => {
const url = `${baseURL}/crop_100%5F50%5F300%5F200,f_auto/images/test.jpg`;
const result = extract(url);
assertEquals(result?.src, "/images/test.jpg");
assertEquals(result?.operations.crop, "100_50_300_200");
});

await t.step("should extract fit and position", () => {
const url =
`${baseURL}/s_800x600,fit_cover,position_top,f_auto/images/test.jpg`;
const result = extract(url);
assertEquals(result?.operations.fit, "cover");
assertEquals(result?.operations.position, "top");
});
});

Deno.test("ipx generate", async (t) => {
Expand Down Expand Up @@ -139,3 +154,36 @@ Deno.test("ipx transform", async (t) => {
);
});
});

Deno.test("ipx generate with extended operations", async (t) => {
await t.step("should generate URL with crop", () => {
const result = generate(
img,
{ width: 800, height: 600, crop: "100_50_300_200" },
{ baseURL },
);
assertEquals(result.includes("crop_100%5F50%5F300%5F200"), true);
assertEquals(result.includes("s_800x600"), true);
});

await t.step("should generate URL with fit and position", () => {
const result = generate(
img,
{ width: 800, height: 600, fit: "cover", position: "top" },
{ baseURL },
);
assertEquals(result.includes("fit_cover"), true);
assertEquals(result.includes("position_top"), true);
});

await t.step("should generate URL with effects", () => {
const result = generate(
img,
{ width: 300, rotate: 90, blur: 5, grayscale: true },
{ baseURL },
);
assertEquals(result.includes("rotate_90"), true);
assertEquals(result.includes("blur_5"), true);
assertEquals(result.includes("grayscale_true"), true);
});
});
72 changes: 72 additions & 0 deletions src/providers/ipx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,78 @@ export interface IPXOperations extends Operations {
* Output format of the image.
*/
f?: ImageFormat | "auto";

/**
* Resize fit mode. Only applies when both width and height are specified.
*/
fit?: "contain" | "cover" | "fill" | "inside" | "outside";

/**
* Position/gravity for resize. Only applies when both width and height are specified.
* @example "top"
*/
position?: string;

/**
* Alias for position.
*/
pos?: string;

/**
* Extract/crop a region of the image.
* Format: "left_top_width_height"
* @example "100_50_300_200"
*/
extract?: string;

/**
* Alias for extract.
*/
crop?: string;

/**
* Rotation angle in degrees.
* @example 90
*/
rotate?: number;

/**
* Flip image vertically.
*/
flip?: boolean;

/**
* Flip image horizontally.
*/
flop?: boolean;

/**
* Blur sigma value.
* @example 5
*/
blur?: number;

/**
* Sharpen sigma value.
* @example 30
*/
sharpen?: number;

/**
* Convert to grayscale.
*/
grayscale?: boolean;

/**
* Background color (hex without #).
* @example "ff0000"
*/
background?: string;

/**
* Alias for background.
*/
b?: string;
}

export interface IPXOptions {
Expand Down