-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
asImageSrc()
, asImageWidthSrcSet()
, `asImagePixelDensit…
…ySrcSet()` (#38) * feat: add `asImageSrc`, `asImageWidthSrcSet`, `asImagePixelDensitiesSrcSet` * refactor: rename `asImagePixelDensitiesSrcSet` file * test: image helpers * chore(deps): update `imgix-url-builder` * feat: add responsive-view-based image srcset builder * feat: add default pixel densities * refactor: `asImageWidthSrcSet()` * feat: return src and srcset from srcset helpers * refactor: image helpers * docs: update examples * chore(deps): update dependencies * test: remove snapshots * test: add snapshots * chore: force ava to run in non-ci mode * Revert "chore: force ava to run in non-ci mode" This reverts commit a37fe39. * chore: lock AVA to v4.0.0 * Revert "chore: lock AVA to v4.0.0" This reverts commit b0612e0. * chore: remove nyc from `unit` script * Revert "chore: remove nyc from `unit` script" This reverts commit a4c54fe. * chore: move snapshots adjacent to test files * chore: revert to AVA 3 * fix: use Next.js's default srcset widths * docs: reformat `pixelDensities` default value description * test: use non-default pixelDensities in test * docs: update `asImagePixelDensitySrcSet()` example with custom pixel densities * chore: fix package-lock.json * fix: apply width to base srcset image in `asImageWidthSrcSet()` with responsive views * fix: reduce number of default widths in `asImageWidthSrcSet()`
- Loading branch information
1 parent
915af37
commit 2b4984a
Showing
9 changed files
with
450 additions
and
2 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { ImageFieldImage } from "@prismicio/types"; | ||
import { | ||
buildPixelDensitySrcSet, | ||
BuildPixelDensitySrcSetParams, | ||
buildURL, | ||
} from "imgix-url-builder"; | ||
|
||
import { imageThumbnail as isImageThumbnailFilled } from "./isFilled"; | ||
|
||
/** | ||
* The return type of `asImagePixelDensitySrcSet()`. | ||
*/ | ||
type AsImagePixelDensitySrcSetReturnType<Field extends ImageFieldImage> = | ||
Field extends ImageFieldImage<"empty"> | ||
? null | ||
: { | ||
/** | ||
* The Image field's image URL with Imgix URL parameters (if given). | ||
*/ | ||
src: string; | ||
|
||
/** | ||
* A pixel-densitye-based `srcset` attribute value for the Image field's | ||
* image with Imgix URL parameters (if given). | ||
*/ | ||
srcset: string; | ||
}; | ||
|
||
/** | ||
* Creates a pixel-density-based `srcset` from an Image field with optional | ||
* image transformations (via Imgix URL parameters). | ||
* | ||
* If a `pixelDensities` parameter is not given, the following pixel densities | ||
* will be used by default: 1, 2, 3. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const srcset = asImagePixelDensitySrcSet(document.data.imageField, { | ||
* pixelDensities: [1, 2], | ||
* sat: -100, | ||
* }); | ||
* // => { | ||
* // src: 'https://images.prismic.io/repo/image.png?sat=-100', | ||
* // srcset: 'https://images.prismic.io/repo/image.png?sat=-100&dpr=1 1x, ' + | ||
* // 'https://images.prismic.io/repo/image.png?sat=-100&dpr=2 2x' | ||
* // } | ||
* ``` | ||
* | ||
* @param field - Image field (or one of its responsive views) from which to get | ||
* an image URL. | ||
* @param params - An object of Imgix URL API parameters. The `pixelDensities` | ||
* parameter defines the resulting `srcset` widths. | ||
* | ||
* @returns A `srcset` attribute value for the Image field with Imgix URL | ||
* parameters (if given). If the Image field is empty, `null` is returned. | ||
* @see Imgix URL parameters reference: https://docs.imgix.com/apis/rendering | ||
*/ | ||
export const asImagePixelDensitySrcSet = <Field extends ImageFieldImage>( | ||
field: Field, | ||
params: Omit<BuildPixelDensitySrcSetParams, "pixelDensities"> & | ||
Partial<Pick<BuildPixelDensitySrcSetParams, "pixelDensities">> = {}, | ||
): AsImagePixelDensitySrcSetReturnType<Field> => { | ||
if (isImageThumbnailFilled(field)) { | ||
const { pixelDensities = [1, 2, 3], ...imgixParams } = params; | ||
|
||
return { | ||
src: buildURL(field.url, imgixParams), | ||
srcset: buildPixelDensitySrcSet(field.url, { | ||
...imgixParams, | ||
pixelDensities, | ||
}), | ||
} as AsImagePixelDensitySrcSetReturnType<Field>; | ||
} else { | ||
return null as AsImagePixelDensitySrcSetReturnType<Field>; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { ImageFieldImage } from "@prismicio/types"; | ||
import { buildURL, ImgixURLParams } from "imgix-url-builder"; | ||
|
||
import { imageThumbnail as isImageThumbnailFilled } from "./isFilled"; | ||
|
||
/** | ||
* The return type of `asImageSrc()`. | ||
*/ | ||
type AsImageSrcReturnType<Field extends ImageFieldImage> = | ||
Field extends ImageFieldImage<"empty"> ? null : string; | ||
|
||
/** | ||
* Returns the URL of an Image field with optional image transformations (via | ||
* Imgix URL parameters). | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const src = asImageSrc(document.data.imageField, { sat: -100 }); | ||
* // => https://images.prismic.io/repo/image.png?sat=-100 | ||
* ``` | ||
* | ||
* @param field - Image field (or one of its responsive views) from which to get | ||
* an image URL. | ||
* @param params - An object of Imgix URL API parameters to transform the image. | ||
* | ||
* @returns The Image field's image URL with transformations applied (if given). | ||
* If the Image field is empty, `null` is returned. | ||
* @see Imgix URL parameters reference: https://docs.imgix.com/apis/rendering | ||
*/ | ||
export const asImageSrc = <Field extends ImageFieldImage>( | ||
field: Field, | ||
params: ImgixURLParams = {}, | ||
): AsImageSrcReturnType<Field> => { | ||
if (isImageThumbnailFilled(field)) { | ||
return buildURL(field.url, params) as AsImageSrcReturnType<Field>; | ||
} else { | ||
return null as AsImageSrcReturnType<Field>; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { ImageFieldImage } from "@prismicio/types"; | ||
import { | ||
buildURL, | ||
buildWidthSrcSet, | ||
BuildWidthSrcSetParams, | ||
} from "imgix-url-builder"; | ||
|
||
import { imageThumbnail as isImageThumbnailFilled } from "./isFilled"; | ||
|
||
/** | ||
* The return type of `asImageWidthSrcSet()`. | ||
*/ | ||
type AsImageWidthSrcSetReturnType<Field extends ImageFieldImage> = | ||
Field extends ImageFieldImage<"empty"> | ||
? null | ||
: { | ||
/** | ||
* The Image field's image URL with Imgix URL parameters (if given). | ||
*/ | ||
src: string; | ||
|
||
/** | ||
* A width-based `srcset` attribute value for the Image field's image | ||
* with Imgix URL parameters (if given). | ||
*/ | ||
srcset: string; | ||
}; | ||
|
||
/** | ||
* Creates a width-based `srcset` from an Image field with optional image | ||
* transformations (via Imgix URL parameters). | ||
* | ||
* If the Image field contains responsive views, each responsive view is used as | ||
* a width in the resulting `srcset`. | ||
* | ||
* If a `widths` parameter is not given, the following widths will be used by | ||
* default: 640, 750, 828, 1080, 1200, 1920, 2048, 3840. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const srcset = asImageWidthSrcSet(document.data.imageField, { | ||
* widths: [400, 800, 1600], | ||
* sat: -100, | ||
* }); | ||
* // => { | ||
* // src: 'https://images.prismic.io/repo/image.png?sat=-100', | ||
* // srcset: 'https://images.prismic.io/repo/image.png?sat=-100&width=400 400w, ' + | ||
* // 'https://images.prismic.io/repo/image.png?sat=-100&width=800 800w,' + | ||
* // 'https://images.prismic.io/repo/image.png?sat=-100&width=1600 1600w' | ||
* // } | ||
* ``` | ||
* | ||
* @param field - Image field (or one of its responsive views) from which to get | ||
* an image URL. | ||
* @param params - An object of Imgix URL API parameters. The `widths` parameter | ||
* defines the resulting `srcset` widths. | ||
* | ||
* @returns A `srcset` attribute value for the Image field with Imgix URL | ||
* parameters (if given). If the Image field is empty, `null` is returned. | ||
* @see Imgix URL parameters reference: https://docs.imgix.com/apis/rendering | ||
*/ | ||
export const asImageWidthSrcSet = <Field extends ImageFieldImage>( | ||
field: Field, | ||
params: Omit<BuildWidthSrcSetParams, "widths"> & | ||
Partial<Pick<BuildWidthSrcSetParams, "widths">> = {}, | ||
): AsImageWidthSrcSetReturnType<Field> => { | ||
if (isImageThumbnailFilled(field)) { | ||
const { widths = [640, 828, 1200, 2048, 3840], ...urlParams } = params; | ||
const { | ||
url, | ||
dimensions, | ||
alt: _alt, | ||
copyright: _copyright, | ||
...responsiveViews | ||
} = field; | ||
|
||
// The Prismic Rest API will always return thumbnail values if | ||
// the base size is filled. | ||
const responsiveViewObjects: ImageFieldImage<"filled">[] = | ||
Object.values(responsiveViews); | ||
|
||
return { | ||
src: buildURL(url, urlParams), | ||
srcset: responsiveViewObjects.length | ||
? [ | ||
buildWidthSrcSet(url, { | ||
...urlParams, | ||
widths: [dimensions.width], | ||
}), | ||
...responsiveViewObjects.map((thumbnail) => { | ||
return buildWidthSrcSet(thumbnail.url, { | ||
...urlParams, | ||
widths: [thumbnail.dimensions.width], | ||
}); | ||
}), | ||
].join(", ") | ||
: buildWidthSrcSet(field.url, { | ||
...urlParams, | ||
widths, | ||
}), | ||
} as AsImageWidthSrcSetReturnType<Field>; | ||
} else { | ||
return null as AsImageWidthSrcSetReturnType<Field>; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { ImageField } from "@prismicio/types"; | ||
import test from "ava"; | ||
|
||
import { asImagePixelDensitySrcSet } from "../src"; | ||
|
||
test("returns an image field pixel-density-based srcset with [1, 2, 3] pxiel densities by default", (t) => { | ||
const field: ImageField = { | ||
url: "https://images.prismic.io/qwerty/image.png?auto=compress%2Cformat", | ||
alt: null, | ||
copyright: null, | ||
dimensions: { width: 400, height: 300 }, | ||
}; | ||
|
||
t.deepEqual(asImagePixelDensitySrcSet(field), { | ||
src: field.url, | ||
srcset: | ||
`${field.url}&dpr=1 1x, ` + | ||
`${field.url}&dpr=2 2x, ` + | ||
`${field.url}&dpr=3 3x`, | ||
}); | ||
}); | ||
|
||
test("supports custom pixel densities", (t) => { | ||
const field: ImageField = { | ||
url: "https://images.prismic.io/qwerty/image.png?auto=compress%2Cformat", | ||
alt: null, | ||
copyright: null, | ||
dimensions: { width: 400, height: 300 }, | ||
}; | ||
|
||
t.deepEqual( | ||
asImagePixelDensitySrcSet(field, { | ||
pixelDensities: [2, 4, 6], | ||
}), | ||
{ | ||
src: field.url, | ||
srcset: | ||
`${field.url}&dpr=2 2x, ` + | ||
`${field.url}&dpr=4 4x, ` + | ||
`${field.url}&dpr=6 6x`, | ||
}, | ||
); | ||
}); | ||
|
||
test("applies given Imgix URL parameters", (t) => { | ||
const field: ImageField = { | ||
url: "https://images.prismic.io/qwerty/image.png?auto=compress%2Cformat", | ||
alt: null, | ||
copyright: null, | ||
dimensions: { width: 400, height: 300 }, | ||
}; | ||
|
||
t.deepEqual( | ||
asImagePixelDensitySrcSet(field, { | ||
sat: 100, | ||
}), | ||
{ | ||
src: `${field.url}&sat=100`, | ||
srcset: | ||
`${field.url}&sat=100&dpr=1 1x, ` + | ||
`${field.url}&sat=100&dpr=2 2x, ` + | ||
`${field.url}&sat=100&dpr=3 3x`, | ||
}, | ||
); | ||
}); | ||
|
||
test("returns null when image field is empty", (t) => { | ||
const field: ImageField<null, "empty"> = {}; | ||
|
||
t.is(asImagePixelDensitySrcSet(field), null); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { ImageField } from "@prismicio/types"; | ||
import test from "ava"; | ||
|
||
import { asImageSrc } from "../src"; | ||
|
||
test("returns an image field URL", (t) => { | ||
const field: ImageField = { | ||
url: "https://images.prismic.io/qwerty/image.png?auto=compress%2Cformat", | ||
alt: null, | ||
copyright: null, | ||
dimensions: { width: 400, height: 300 }, | ||
}; | ||
|
||
t.is(asImageSrc(field), field.url); | ||
}); | ||
|
||
test("applies given Imgix URL parameters", (t) => { | ||
const field: ImageField = { | ||
url: "https://images.prismic.io/qwerty/image.png?auto=compress%2Cformat", | ||
alt: null, | ||
copyright: null, | ||
dimensions: { width: 400, height: 300 }, | ||
}; | ||
|
||
t.is(asImageSrc(field, { sat: 100 }), `${field.url}&sat=100`); | ||
}); | ||
|
||
test("returns null when image field is empty", (t) => { | ||
const field: ImageField<null, "empty"> = {}; | ||
|
||
t.is(asImageSrc(field), null); | ||
}); |
Oops, something went wrong.