diff --git a/README.md b/README.md index 2606240..8e2cd84 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,12 @@ Return the url as a string. Specify the number of pixels to pad the image. +### `frame(value)` + +Specify the frame of an animated image to transform. Acceptable values: + +- `1` - Returns the first frame of the animated image as a static preview of the image. + ### Deprecated: `minWidth(pixels)`, `maxWidth(pixels)`, `minHeight(pixels)`, `maxHeight(pixels)` Specifies min/max dimensions when cropping. diff --git a/src/builder.ts b/src/builder.ts index 257a65f..4babc41 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -247,6 +247,14 @@ export class ImageUrlBuilder { return this.withOptions({pad}) } + frame(frame: number) { + if (frame !== 1) { + throw new Error(`Invalid frame value "${frame}"`) + } + + return this.withOptions({frame}) + } + // Gets the url based on the submitted parameters url() { return urlForImage(this.options) diff --git a/src/types.ts b/src/types.ts index 41dbb9d..0faf3a2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -26,6 +26,7 @@ export type ImageUrlBuilderOptions = Partial & { saturation?: number auto?: AutoMode pad?: number + frame?: number } export type ImageUrlBuilderOptionsWithAliases = ImageUrlBuilderOptions & { diff --git a/src/urlForImage.ts b/src/urlForImage.ts index a041a7b..f39ee30 100644 --- a/src/urlForImage.ts +++ b/src/urlForImage.ts @@ -31,6 +31,7 @@ export const SPEC_NAME_TO_URL_NAME_MAPPINGS = [ ['auto', 'auto'], ['dpr', 'dpr'], ['pad', 'pad'], + ['frame', 'frame'] ] export default function urlForImage(options: ImageUrlBuilderOptions): string { diff --git a/test/__snapshots__/builder.test.ts.snap b/test/__snapshots__/builder.test.ts.snap index c443ce6..b29b5e3 100644 --- a/test/__snapshots__/builder.test.ts.snap +++ b/test/__snapshots__/builder.test.ts.snap @@ -1,8 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`builder all hotspot/crop-compatible params 1`] = `"rect=200,300,1600,2400&flip=hv&fm=png&dl=a.png&blur=50&sharp=7&invert=true&or=90&min-h=150&max-h=300&min-w=100&max-w=200&q=50&fit=crop&auto=format&pad=40"`; +exports[`builder all hotspot/crop-compatible params 1`] = `"rect=200,300,1600,2400&flip=hv&fm=png&dl=a.png&blur=50&sharp=7&invert=true&or=90&min-h=150&max-h=300&min-w=100&max-w=200&q=50&fit=crop&auto=format&pad=40&frame=1"`; -exports[`builder all params 1`] = `"rect=10,20,30,40&bg=bf1942&fp-x=10&fp-y=20&flip=hv&fm=png&dl=a.png&blur=50&invert=true&or=90&min-h=150&max-h=300&min-w=100&max-w=200&q=50&fit=crop&crop=center&auto=format&pad=40"`; +exports[`builder all params 1`] = `"rect=10,20,30,40&bg=bf1942&fp-x=10&fp-y=20&flip=hv&fm=png&dl=a.png&blur=50&invert=true&or=90&min-h=150&max-h=300&min-w=100&max-w=200&q=50&fit=crop&crop=center&auto=format&pad=40&frame=1"`; exports[`builder automatic format 1`] = `"auto=format"`; @@ -24,6 +24,8 @@ exports[`builder flip horizontal 1`] = `"flip=h"`; exports[`builder flip vertical 1`] = `"flip=v"`; +exports[`builder frame = 1 1`] = `"frame=1"`; + exports[`builder handles crop and hotspot being set to null (GraphQL) 1`] = `"https://cdn.sanity.io/images/zp7mbokg/production/Tb9Ew8CXIwaY6R1kjMvI0uRR-2000x3000.jpg"`; exports[`builder handles crop but no hotspot 1`] = `"https://cdn.sanity.io/images/zp7mbokg/production/Tb9Ew8CXIwaY6R1kjMvI0uRR-2000x3000.jpg?rect=200,300,1600,2400"`; diff --git a/test/builder.test.ts b/test/builder.test.ts index 6d709c0..192bbda 100644 --- a/test/builder.test.ts +++ b/test/builder.test.ts @@ -129,6 +129,11 @@ const cases = [ url: stripPath(urlFor.image(noHotspotImage()).pad(50).url()), }, + { + name: 'frame = 1', + url: stripPath(urlFor.image(noHotspotImage()).frame(1).url()), + }, + { name: 'automatic format', url: stripPath(urlFor.image(noHotspotImage()).auto('format').url()), @@ -176,6 +181,7 @@ const cases = [ .flipVertical() .fit('crop') .pad(40) + .frame(1) .url() ), }, @@ -204,6 +210,7 @@ const cases = [ .fit('crop') .crop('center') .pad(40) + .frame(1) .url() ), }, @@ -230,4 +237,9 @@ describe('builder', () => { // @ts-ignore: Because we're throwing on invalids expect(() => urlFor.image(croppedImage()).auto('moo')).toThrowError(/Invalid auto mode "moo"/) }) + + test('should throw on invalid frame number', () => { + // @ts-ignore: Because we're throwing on invalids + expect(() => urlFor.image(croppedImage()).frame(2)).toThrowError(/Invalid frame value "2"/) + }) })