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/brown-mangos-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@imgproxy/imgproxy-js-core": minor
---

Add [flip](https://docs.imgproxy.net/latest/usage/processing#flip) option support
20 changes: 20 additions & 0 deletions src/options/flip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { FlipOptions, FlipOptionsPartial } from "../types/flip";
import { guardIsUndef, normalizeBoolean } from "../utils";

const getOpt = (options: FlipOptionsPartial): FlipOptions | undefined =>
options.flip || options.fl;

const test = (options: FlipOptionsPartial): boolean => Boolean(getOpt(options));

const build = (options: FlipOptionsPartial): string => {
const flipOptions = getOpt(options);

guardIsUndef(flipOptions, "flip");

const horizontal = flipOptions.horizontal ?? false;
const vertical = flipOptions.vertical ?? false;

return `fl:${normalizeBoolean(horizontal)}:${normalizeBoolean(vertical)}`;
};

export { test, build };
1 change: 1 addition & 0 deletions src/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export * as extend from "./extend";
export * as extendAspectRatio from "./extendAspectRatio";
export * as fallbackImageUrl from "./fallbackImageUrl";
export * as filename from "./filename";
export * as flip from "./flip";
export * as format from "./format";
export * as formatQuality from "./formatQuality";
export * as gradient from "./gradient";
Expand Down
43 changes: 43 additions & 0 deletions src/types/flip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Boolean-like values for flip options
*
* @note Only `1`, `"t"`, or `true` are recognized as truthy values.
* Any other value (including `"true"` or `"1"` as strings) will be treated as false.
*/
type FlipBooleanValue = boolean | 1 | 0 | "t" | "f";

/**
* *Flip option*
*
* When set, imgproxy will flip the image along the specified axes.
*
* @default false:false
*
* @see {@link https://docs.imgproxy.net/latest/usage/processing#flip | Flip imgproxy docs}
*/
type FlipOptions = {
/**
* When set to `1`, `"t"`, or boolean `true`, imgproxy will flip the image horizontally.
* @default false
*/
horizontal?: FlipBooleanValue;
/**
* When set to `1`, `t`, or boolean `true`, imgproxy will flip the image vertically.
* @default false
*/
vertical?: FlipBooleanValue;
};

/**
* *Flip option*
*
* To describe the flip option, you can use the keyword `flip` or `fl`.
*
* @see https://docs.imgproxy.net/latest/usage/processing#flip
*/
interface FlipOptionsPartial {
flip?: FlipOptions;
fl?: FlipOptions;
}

export { FlipOptions, FlipOptionsPartial };
2 changes: 2 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import type { ExtendAspectRatioOptionsPartial } from "./extendAspectRatio";
import type { ExtendOptionsPartial } from "./extend";
import type { FallbackImageUrlOptionsPartial } from "./fallbackImageUrl";
import type { FilenameOptionsPartial } from "./filename";
import type { FlipOptionsPartial } from "./flip";
import type { FormatOptionsPartial } from "./format";
import type { FormatQualityOptionsPartial } from "./formatQuality";
import type { GradientOptionsPartial } from "./gradient";
Expand Down Expand Up @@ -105,6 +106,7 @@ export type Options = AdjustOptionsPartial &
ExtendOptionsPartial &
FallbackImageUrlOptionsPartial &
FilenameOptionsPartial &
FlipOptionsPartial &
FormatOptionsPartial &
FormatQualityOptionsPartial &
GradientOptionsPartial &
Expand Down
88 changes: 88 additions & 0 deletions tests/optionsBasic/flip.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { describe, expect, it } from "vitest";
import { test, build } from "../../src/options/flip";

describe("flip", () => {
describe("test", () => {
it("should return true if flip option is defined", () => {
expect(test({ flip: { horizontal: true } })).toEqual(true);
});

it("should return true if fl option is defined", () => {
expect(test({ fl: { vertical: true } })).toEqual(true);
});

it("should return false if flip option is undefined", () => {
expect(test({})).toEqual(false);
});
});

describe("build", () => {
it("should throw an error if flip is undefined", () => {
expect(() => build({})).toThrow("flip option is undefined");
});

it("should return fl:f:f if both horizontal and vertical are false", () => {
expect(build({ flip: { horizontal: false, vertical: false } })).toEqual(
"fl:f:f"
);
});

it("should return fl:f:f if flip object is empty (defaults)", () => {
expect(build({ flip: {} })).toEqual("fl:f:f");
});

it("should return fl:t:f if horizontal is true", () => {
expect(build({ flip: { horizontal: true } })).toEqual("fl:t:f");
});

it("should return fl:f:t if vertical is true", () => {
expect(build({ flip: { vertical: true } })).toEqual("fl:f:t");
});

it("should return fl:t:t if both are true", () => {
expect(build({ flip: { horizontal: true, vertical: true } })).toEqual(
"fl:t:t"
);
});

it("should support horizontal as 1", () => {
expect(build({ flip: { horizontal: 1 } })).toEqual("fl:t:f");
});

it("should support horizontal as 't'", () => {
expect(build({ flip: { horizontal: "t" } })).toEqual("fl:t:f");
});

it("should support vertical as 1", () => {
expect(build({ flip: { vertical: 1 } })).toEqual("fl:f:t");
});

it("should support vertical as 't'", () => {
expect(build({ flip: { vertical: "t" } })).toEqual("fl:f:t");
});

it("should support both with various truthy values", () => {
expect(build({ flip: { horizontal: 1, vertical: "t" } })).toEqual(
"fl:t:t"
);
});

it("should support 0 as false for horizontal", () => {
expect(build({ flip: { horizontal: 0, vertical: true } })).toEqual(
"fl:f:t"
);
});

it("should work with fl shorthand", () => {
expect(build({ fl: { horizontal: true, vertical: false } })).toEqual(
"fl:t:f"
);
});

it("should work with both horizontal and vertical using different value types", () => {
expect(build({ flip: { horizontal: true, vertical: 1 } })).toEqual(
"fl:t:t"
);
});
});
});