Skip to content

Commit e619141

Browse files
committed
Add avifo option support
1 parent a8d2c05 commit e619141

File tree

6 files changed

+150
-0
lines changed

6 files changed

+150
-0
lines changed

.changeset/small-views-battle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@imgproxy/imgproxy-js-core": minor
3+
---
4+
5+
Add [avifo](https://docs.imgproxy.net/latest/usage/processing#avif-options) option support

src/options/avifOptions.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { AvifOptions, AvifOptionsPartial } from "../types/avifOptions";
2+
import { guardIsUndef, guardIsValidVal } from "../utils";
3+
4+
const correctOptions = {
5+
auto: true,
6+
on: true,
7+
off: true,
8+
};
9+
10+
const getOpt = (options: AvifOptionsPartial): AvifOptions | undefined =>
11+
options.avif_options || options.avifo;
12+
13+
const test = (options: AvifOptionsPartial): boolean => Boolean(getOpt(options));
14+
15+
const build = (options: AvifOptionsPartial): string => {
16+
const avifOptions = getOpt(options);
17+
let subsample: string;
18+
19+
guardIsUndef(avifOptions, "avif_options");
20+
21+
if (typeof avifOptions === "string") {
22+
subsample = avifOptions;
23+
} else {
24+
subsample = avifOptions.subsample;
25+
}
26+
27+
guardIsValidVal(correctOptions, subsample, "avif_options");
28+
29+
return `avifo:${subsample}`;
30+
};
31+
32+
export { test, build };

src/options/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * as adjust from "./adjust";
22
export * as autoquality from "./autoquality";
33
export * as autoRotate from "./autoRotate";
4+
export * as avifOptions from "./avifOptions";
45
export * as background from "./background";
56
export * as backgroundAlpha from "./backgroundAlpha";
67
export * as blur from "./blur";

src/types/avifOptions.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Available AVIF subsample values:
3+
* - `"auto"` - (default) use subsampling when the image is saved with quality less than 90
4+
* - `"on"` - always apply subsampling
5+
* - `"off"` - never apply subsampling
6+
*/
7+
type AvifSubsampleOptions = "auto" | "on" | "off";
8+
9+
/**
10+
* *AVIF options*. **PRO feature**
11+
*
12+
* Allows redefining AVIF saving options.
13+
*
14+
* @default "auto"
15+
*
16+
* @see {@link https://docs.imgproxy.net/generating_the_url?id=avif-options | AVIF options imgproxy docs}
17+
*/
18+
type AvifOptions =
19+
| AvifSubsampleOptions
20+
| {
21+
/**
22+
* Controls when chroma subsampling is used. Default: `"auto"`
23+
*/
24+
subsample: AvifSubsampleOptions;
25+
};
26+
27+
/**
28+
* *AVIF options option*. **PRO feature**
29+
*
30+
* To describe the AVIF options option, you can use the keyword `avif_options` or `avifo`.
31+
*
32+
* @see https://docs.imgproxy.net/generating_the_url?id=avif-options
33+
*/
34+
interface AvifOptionsPartial {
35+
avif_options?: AvifOptions;
36+
avifo?: AvifOptions;
37+
}
38+
39+
export { AvifOptions, AvifOptionsPartial };

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { AdjustOptionsPartial } from "./adjust";
22
import type { AutoqualityOptionsPartial } from "./autoquality";
33
import type { AutoRotateOptionsPartial } from "./autoRotate";
4+
import type { AvifOptionsPartial } from "./avifOptions";
45
import type { BackgroundOptionsPartial } from "./background";
56
import type { BackgroundAlphaOptionsPartial } from "./backgroundAlpha";
67
import type { BlurDetectionsOptionsPartial } from "./blurDetections";
@@ -80,6 +81,7 @@ import type { WildOptionsPartial } from "../typesShared/wildOptions";
8081
export type Options = AdjustOptionsPartial &
8182
AutoqualityOptionsPartial &
8283
AutoRotateOptionsPartial &
84+
AvifOptionsPartial &
8385
BackgroundOptionsPartial &
8486
BackgroundAlphaOptionsPartial &
8587
BlurDetectionsOptionsPartial &
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { describe, expect, it } from "vitest";
2+
import { test, build } from "../../src/options/avifOptions";
3+
4+
describe("avifOptions", () => {
5+
describe("test", () => {
6+
it("should return true if avif_options option is defined", () => {
7+
expect(test({ avif_options: "auto" })).toEqual(true);
8+
});
9+
10+
it("should return true if avifo option is defined", () => {
11+
expect(test({ avifo: "on" })).toEqual(true);
12+
});
13+
14+
it("should return false if avif_options option is undefined", () => {
15+
expect(test({})).toEqual(false);
16+
});
17+
});
18+
19+
describe("build", () => {
20+
it("should throw an error if avif_options is undefined", () => {
21+
expect(() => build({})).toThrow("avif_options option is undefined");
22+
});
23+
24+
it("should throw an error if avif_options is invalid", () => {
25+
// @ts-expect-error: Let's ignore an error (check for users with vanilla js).
26+
expect(() => build({ avif_options: "invalid" })).toThrow(
27+
"avif_options option is invalid. Valid values are: auto, on, off"
28+
);
29+
});
30+
31+
it("should throw an error if avif_options is a number", () => {
32+
// @ts-expect-error: Let's ignore an error (check for users with vanilla js).
33+
expect(() => build({ avif_options: 1 })).toThrow(
34+
"avif_options option is invalid. Valid values are: auto, on, off"
35+
);
36+
});
37+
38+
it("should return avifo:auto if avif_options is auto", () => {
39+
expect(build({ avif_options: "auto" })).toEqual("avifo:auto");
40+
});
41+
42+
it("should return avifo:on if avifo option is on", () => {
43+
expect(build({ avifo: "on" })).toEqual("avifo:on");
44+
});
45+
46+
it("should return avifo:off if avif_options is off", () => {
47+
expect(build({ avif_options: "off" })).toEqual("avifo:off");
48+
});
49+
50+
it("should support object notation with subsample property", () => {
51+
expect(build({ avif_options: { subsample: "auto" } })).toEqual(
52+
"avifo:auto"
53+
);
54+
55+
expect(build({ avif_options: { subsample: "on" } })).toEqual("avifo:on");
56+
57+
expect(build({ avif_options: { subsample: "off" } })).toEqual(
58+
"avifo:off"
59+
);
60+
});
61+
62+
it("should throw an error if subsample is invalid in object notation", () => {
63+
expect(() =>
64+
// @ts-expect-error: Let's ignore an error (check for users with vanilla js).
65+
build({ avif_options: { subsample: "invalid" } })
66+
).toThrow(
67+
"avif_options option is invalid. Valid values are: auto, on, off"
68+
);
69+
});
70+
});
71+
});

0 commit comments

Comments
 (0)