Skip to content

Commit

Permalink
feat: add netlify provider (#299)
Browse files Browse the repository at this point in the history
LFS only
  • Loading branch information
danielroe committed May 29, 2021
1 parent 828b9f9 commit 003e144
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs/pages/en/4.providers/netlify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Netlify Provider
description: Optimize images with Netlify's dynamic image transformation service.
navigation:
title: Netlify
---

Netlify offers dynamic image transformation for all JPEG, PNG, and GIF files you have set to be tracked with [Netlify Large Media](https://docs.netlify.com/large-media/overview/).

:::alert{type="warning"}
Before setting `provider: 'netlify'`, make sure you have followed the steps to enable [Netlify Large Media](https://docs.netlify.com/large-media/overview/).
:::

## Modifiers

In addition to `height` and `width`, the Netlify provider supports the following modifiers:

### `fit`

* **Default**: `contain`
* **Valid options**: `contain` (equivalent to `nf_resize=fit`) and `fill` (equivalent to `nf_resize=smartcrop`)
3 changes: 3 additions & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export default <NuxtConfig> {
imagekit: {
baseURL: 'https://ik.imagekit.io/demo'
},
netlify: {
baseURL: 'https://netlify-photo-gallery.netlify.app'
},
prismic: {},
sanity: {
projectId: 'j1o4tmjp'
Expand Down
17 changes: 17 additions & 0 deletions playground/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,23 @@ export const providers: Provider[] = [
{ src: '/plant.jpeg' }
]
},
// Netlify
{
name: 'netlify',
samples: [
{
src: '/images/apple.jpg',
width: 101,
fit: 'contain'
},
{
src: '/images/apple.jpg',
width: 200,
height: 200,
fit: 'fill'
}
]
},
// Prismic
{
name: 'prismic',
Expand Down
1 change: 1 addition & 0 deletions src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const BuiltInProviders = [
'imagekit',
'imgix',
'ipx',
'netlify',
'prismic',
'sanity',
'static',
Expand Down
50 changes: 50 additions & 0 deletions src/runtime/providers/netlify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { joinURL } from 'ufo'
import type { ProviderGetImage } from 'src'
import { createOperationsGenerator } from '~image'

export const operationsGenerator = createOperationsGenerator({
keyMap: {
height: 'h',
fit: 'nf_resize',
width: 'w'
},
valueMap: {
fit: {
fill: 'smartcrop',
contain: 'fit'
}
},
joinWith: '&',
formatter: (key, value) => `${key}=${value}`
})

const isDev = process.env.NODE_ENV === 'development'

// https://docs.netlify.com/large-media/transform-images/

export const getImage: ProviderGetImage = (src, { modifiers = {}, baseURL = '/' } = {}) => {
if (modifiers.format) {
// Not currently supported
delete modifiers.format
}
const hasTransformation = modifiers.height || modifiers.width
if (!modifiers.fit && hasTransformation) {
// fit is required for resizing images
modifiers.fit = 'contain'
}
if (hasTransformation && modifiers.fit !== 'contain' && !(modifiers.height && modifiers.width)) {
// smartcrop is only supported with both height and width
if (isDev) {
// eslint-disable-next-line
console.warn(`Defaulting to fit=contain as smart cropping is only supported when providing both height and width. Warning originated from \`${src}\`.`)
}
modifiers.fit = 'contain'
}
if (isDev) {
return { url: src }
}
const operations = operationsGenerator(modifiers)
return {
url: joinURL(baseURL, src + (operations ? ('?' + operations) : ''))
}
}
6 changes: 6 additions & 0 deletions test/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const images = [
fastly: { url: '/test.png' },
imgix: { url: '/test.png' },
imagekit: { url: '/test.png' },
netlify: { url: '/test.png' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=100&h=100' }
},
{
Expand All @@ -17,6 +18,7 @@ export const images = [
fastly: { url: '/test.png?width=200' },
imgix: { url: '/test.png?w=200' },
imagekit: { url: '/test.png?tr=w-200' },
netlify: { url: '/test.png?w=200&nf_resize=fit' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=200&h=100' }
},
{
Expand All @@ -27,6 +29,7 @@ export const images = [
fastly: { url: '/test.png?height=200' },
imgix: { url: '/test.png?h=200' },
imagekit: { url: '/test.png?tr=h-200' },
netlify: { url: '/test.png?h=200&nf_resize=fit' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=100&h=200' }
},
{
Expand All @@ -37,6 +40,7 @@ export const images = [
fastly: { url: '/test.png?width=200&height=200' },
imgix: { url: '/test.png?w=200&h=200' },
imagekit: { url: '/test.png?tr=w-200,h-200' },
netlify: { url: '/test.png?w=200&h=200&nf_resize=fit' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=200&h=200' }
},
{
Expand All @@ -47,6 +51,7 @@ export const images = [
fastly: { url: '/test.png?width=200&height=200&fit=bounds' },
imgix: { url: '/test.png?w=200&h=200&fit=fill' },
imagekit: { url: '/test.png?tr=w-200,h-200,cm-pad_resize' },
netlify: { url: '/test.png?w=200&h=200&nf_resize=fit' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=200&h=200&fit=fill' }
},
{
Expand All @@ -57,6 +62,7 @@ export const images = [
fastly: { url: '/test.png?width=200&height=200&fit=bounds&format=jpeg' },
imgix: { url: '/test.png?w=200&h=200&fit=fill&fm=jpeg' },
imagekit: { url: '/test.png?tr=w-200,h-200,cm-pad_resize,f-jpeg' },
netlify: { url: '/test.png?w=200&h=200&nf_resize=fit' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=200&h=200&fit=fill&fm=jpeg' }
}
] as const
Expand Down
13 changes: 13 additions & 0 deletions test/unit/providers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as twicpics from '~/runtime/providers/twicpics'
import * as fastly from '~/runtime/providers/fastly'
import * as imgix from '~/runtime/providers/imgix'
import * as imagekit from '~/runtime/providers/imagekit'
import * as netlify from '~/runtime/providers/netlify'
import * as prismic from '~/runtime/providers/prismic'

describe('Providers', () => {
Expand Down Expand Up @@ -120,6 +121,18 @@ describe('Providers', () => {
}
})

test('netlify', () => {
const providerOptions = {
baseURL: ''
}

for (const image of images) {
const [src, modifiers] = image.args
const generated = netlify.getImage(src, { modifiers: { ...modifiers }, ...providerOptions }, {} as any)
expect(generated).toMatchObject(image.netlify)
}
})

test('prismic', () => {
const providerOptions = {
baseURL: '' // Use empty base URL for the sake of simplicity
Expand Down

0 comments on commit 003e144

Please sign in to comment.