Skip to content

Commit 1010eaf

Browse files
committed
Add flip option support
1 parent a8fed05 commit 1010eaf

File tree

6 files changed

+159
-0
lines changed

6 files changed

+159
-0
lines changed

.changeset/brown-mangos-fetch.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 [flip](https://docs.imgproxy.net/latest/usage/processing#flip) option support

src/options/flip.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { FlipOptions, FlipOptionsPartial } from "../types/flip";
2+
import { guardIsUndef, normalizeBoolean } from "../utils";
3+
4+
const getOpt = (options: FlipOptionsPartial): FlipOptions | undefined =>
5+
options.flip || options.fl;
6+
7+
const test = (options: FlipOptionsPartial): boolean => Boolean(getOpt(options));
8+
9+
const build = (options: FlipOptionsPartial): string => {
10+
const flipOptions = getOpt(options);
11+
12+
guardIsUndef(flipOptions, "flip");
13+
14+
const horizontal = flipOptions.horizontal ?? false;
15+
const vertical = flipOptions.vertical ?? false;
16+
17+
return `fl:${normalizeBoolean(horizontal)}:${normalizeBoolean(vertical)}`;
18+
};
19+
20+
export { test, build };

src/options/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export * as extend from "./extend";
2525
export * as extendAspectRatio from "./extendAspectRatio";
2626
export * as fallbackImageUrl from "./fallbackImageUrl";
2727
export * as filename from "./filename";
28+
export * as flip from "./flip";
2829
export * as format from "./format";
2930
export * as formatQuality from "./formatQuality";
3031
export * as gradient from "./gradient";

src/types/flip.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Boolean-like values for flip options
3+
*
4+
* @note Only `1`, `"t"`, or `true` are recognized as truthy values.
5+
* Any other value (including `"true"` or `"1"` as strings) will be treated as false.
6+
*/
7+
type FlipBooleanValue = boolean | 1 | 0 | "t" | "f";
8+
9+
/**
10+
* *Flip option*
11+
*
12+
* When set, imgproxy will flip the image along the specified axes.
13+
*
14+
* @default false:false
15+
*
16+
* @see {@link https://docs.imgproxy.net/latest/usage/processing#flip | Flip imgproxy docs}
17+
*/
18+
type FlipOptions = {
19+
/**
20+
* When set to `1`, `"t"`, or boolean `true`, imgproxy will flip the image horizontally.
21+
* @default false
22+
*/
23+
horizontal?: FlipBooleanValue;
24+
/**
25+
* When set to `1`, `t`, or boolean `true`, imgproxy will flip the image vertically.
26+
* @default false
27+
*/
28+
vertical?: FlipBooleanValue;
29+
};
30+
31+
/**
32+
* *Flip option*
33+
*
34+
* To describe the flip option, you can use the keyword `flip` or `fl`.
35+
*
36+
* @see https://docs.imgproxy.net/latest/usage/processing#flip
37+
*/
38+
interface FlipOptionsPartial {
39+
flip?: FlipOptions;
40+
fl?: FlipOptions;
41+
}
42+
43+
export { FlipOptions, FlipOptionsPartial };

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import type { ExtendAspectRatioOptionsPartial } from "./extendAspectRatio";
2525
import type { ExtendOptionsPartial } from "./extend";
2626
import type { FallbackImageUrlOptionsPartial } from "./fallbackImageUrl";
2727
import type { FilenameOptionsPartial } from "./filename";
28+
import type { FlipOptionsPartial } from "./flip";
2829
import type { FormatOptionsPartial } from "./format";
2930
import type { FormatQualityOptionsPartial } from "./formatQuality";
3031
import type { GradientOptionsPartial } from "./gradient";
@@ -105,6 +106,7 @@ export type Options = AdjustOptionsPartial &
105106
ExtendOptionsPartial &
106107
FallbackImageUrlOptionsPartial &
107108
FilenameOptionsPartial &
109+
FlipOptionsPartial &
108110
FormatOptionsPartial &
109111
FormatQualityOptionsPartial &
110112
GradientOptionsPartial &

tests/optionsBasic/flip.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { describe, expect, it } from "vitest";
2+
import { test, build } from "../../src/options/flip";
3+
4+
describe("flip", () => {
5+
describe("test", () => {
6+
it("should return true if flip option is defined", () => {
7+
expect(test({ flip: { horizontal: true } })).toEqual(true);
8+
});
9+
10+
it("should return true if fl option is defined", () => {
11+
expect(test({ fl: { vertical: true } })).toEqual(true);
12+
});
13+
14+
it("should return false if flip option is undefined", () => {
15+
expect(test({})).toEqual(false);
16+
});
17+
});
18+
19+
describe("build", () => {
20+
it("should throw an error if flip is undefined", () => {
21+
expect(() => build({})).toThrow("flip option is undefined");
22+
});
23+
24+
it("should return fl:f:f if both horizontal and vertical are false", () => {
25+
expect(build({ flip: { horizontal: false, vertical: false } })).toEqual(
26+
"fl:f:f"
27+
);
28+
});
29+
30+
it("should return fl:f:f if flip object is empty (defaults)", () => {
31+
expect(build({ flip: {} })).toEqual("fl:f:f");
32+
});
33+
34+
it("should return fl:t:f if horizontal is true", () => {
35+
expect(build({ flip: { horizontal: true } })).toEqual("fl:t:f");
36+
});
37+
38+
it("should return fl:f:t if vertical is true", () => {
39+
expect(build({ flip: { vertical: true } })).toEqual("fl:f:t");
40+
});
41+
42+
it("should return fl:t:t if both are true", () => {
43+
expect(build({ flip: { horizontal: true, vertical: true } })).toEqual(
44+
"fl:t:t"
45+
);
46+
});
47+
48+
it("should support horizontal as 1", () => {
49+
expect(build({ flip: { horizontal: 1 } })).toEqual("fl:t:f");
50+
});
51+
52+
it("should support horizontal as 't'", () => {
53+
expect(build({ flip: { horizontal: "t" } })).toEqual("fl:t:f");
54+
});
55+
56+
it("should support vertical as 1", () => {
57+
expect(build({ flip: { vertical: 1 } })).toEqual("fl:f:t");
58+
});
59+
60+
it("should support vertical as 't'", () => {
61+
expect(build({ flip: { vertical: "t" } })).toEqual("fl:f:t");
62+
});
63+
64+
it("should support both with various truthy values", () => {
65+
expect(build({ flip: { horizontal: 1, vertical: "t" } })).toEqual(
66+
"fl:t:t"
67+
);
68+
});
69+
70+
it("should support 0 as false for horizontal", () => {
71+
expect(build({ flip: { horizontal: 0, vertical: true } })).toEqual(
72+
"fl:f:t"
73+
);
74+
});
75+
76+
it("should work with fl shorthand", () => {
77+
expect(build({ fl: { horizontal: true, vertical: false } })).toEqual(
78+
"fl:t:f"
79+
);
80+
});
81+
82+
it("should work with both horizontal and vertical using different value types", () => {
83+
expect(build({ flip: { horizontal: true, vertical: 1 } })).toEqual(
84+
"fl:t:t"
85+
);
86+
});
87+
});
88+
});

0 commit comments

Comments
 (0)