Skip to content

Commit

Permalink
feat: cloudflare provider (nuxt#359)
Browse files Browse the repository at this point in the history
Co-authored-by: pooya parsa <[email protected]>
  • Loading branch information
shadow81627 and pi0 committed Jun 21, 2022
1 parent ad73348 commit 59ac32c
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 0 deletions.
38 changes: 38 additions & 0 deletions docs/content/en/4.providers/cloudflare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Cloudflare Provider
description: 'Nuxt Image has first class integration with Cloudflare'
navigation:
title: Cloudflare
---

Integration between [Cloudflare](https://developers.cloudflare.com/images/) and the image module.

:::alert{type="info"}
Availability only for Business and Enterprise Customers. Normally Cloudflare [pages](https://pages.cloudflare.com/) users can already benefit from build-time image optimization.
:::

To use this provider you just need to specify the base url (zone) of your service:

```js{}[nuxt.config.js]
export default {
image: {
baseURL: 'https://that-test.site'
}
}
```

**Example:**

```vue
<nuxt-img provider="cloudflare" src="/burger.jpeg" height="300" :modifiers="{ fit: 'contain' }" />
```

## Options

### `baseURL`

Default: `/`

Your deployment's domain (zone).

**Note:** `/cdn-cgi/image/` will be automatically appended for generating URLs.
3 changes: 3 additions & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export default <NuxtConfig> {
storyblok: {
baseURL: 'https://a.storyblok.com/'
},
cloudflare: {
baseURL: 'https://that-test.site'
},
cloudinary: {
baseURL: 'https://res.cloudinary.com/nuxt/image/upload/'
},
Expand Down
11 changes: 11 additions & 0 deletions playground/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ export const providers: Provider[] = [
}
]
},
// Cloudflare
{
name: 'cloudflare',
samples: [
{
src: 'https://s3.that-test.site/burger.jpeg',
height: 300,
fit: 'contain'
}
]
},
// Cloudinary
{
name: 'cloudinary',
Expand Down
1 change: 1 addition & 0 deletions src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { ModuleOptions, InputProvider, ImageModuleProvider, ProviderSetup }
import { ipxSetup } from './ipx'

const BuiltInProviders = [
'cloudflare',
'cloudinary',
'contentful',
'cloudimage',
Expand Down
49 changes: 49 additions & 0 deletions src/runtime/providers/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { joinURL, encodeQueryItem } from 'ufo'
import { ProviderGetImage } from 'src'
import { createOperationsGenerator } from '~image'

const operationsGenerator = createOperationsGenerator({
keyMap: {
width: 'w',
height: 'h',
dpr: 'dpr',
fit: 'fit',
gravity: 'g',
quality: 'q',
format: 'f',
sharpen: 'sharpen'
},
valueMap: {
fit: {
cover: 'cover',
contain: 'contain',
fill: 'scale-down',
outside: 'crop',
inside: 'pad'
},
gravity: {
auto: 'auto',
side: 'side'
}
},
joinWith: ',',
formatter: (key, val) => encodeQueryItem(key, val)
})

const defaultModifiers = {}

// https://developers.cloudflare.com/images/image-resizing/url-format/
export const getImage: ProviderGetImage = (src, {
modifiers = {},
baseURL = '/'
} = {}) => {
const mergeModifiers = { ...defaultModifiers, ...modifiers }
const operations = operationsGenerator(mergeModifiers as any)

// https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>
const url = operations ? joinURL(baseURL, 'cdn-cgi/image', operations, src) : joinURL(baseURL, src)

return {
url
}
}
1 change: 1 addition & 0 deletions src/types/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface CloudinaryOptions {
}

export interface ImageProviders {
cloudflare?: any
cloudinary?: Partial<CloudinaryOptions>
contentful?: any
cloudimage?: any
Expand Down
6 changes: 6 additions & 0 deletions test/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const images = [
{
args: ['/test.png', {}],
ipx: { url: '/_ipx/_/test.png' },
cloudflare: { url: '/test.png' },
cloudinary: { url: '/f_auto,q_auto/test' },
twicpics: { url: '/test.png' },
fastly: { url: '/test.png' },
Expand All @@ -20,6 +21,7 @@ export const images = [
{
args: ['/test.png', { width: 200 }],
ipx: { url: '/_ipx/w_200/test.png' },
cloudflare: { url: '/cdn-cgi/image/w=200/test.png' },
cloudinary: { url: '/f_auto,q_auto,w_200/test' },
twicpics: { url: '/test.png?twic=v1/cover=200x-' },
fastly: { url: '/test.png?width=200' },
Expand All @@ -38,6 +40,7 @@ export const images = [
{
args: ['/test.png', { height: 200 }],
ipx: { url: '/_ipx/h_200/test.png' },
cloudflare: { url: '/cdn-cgi/image/h=200/test.png' },
cloudinary: { url: '/f_auto,q_auto,h_200/test' },
twicpics: { url: '/test.png?twic=v1/cover=-x200' },
fastly: { url: '/test.png?height=200' },
Expand All @@ -56,6 +59,7 @@ export const images = [
{
args: ['/test.png', { width: 200, height: 200 }],
ipx: { url: '/_ipx/s_200x200/test.png' },
cloudflare: { url: '/cdn-cgi/image/w=200,h=200/test.png' },
cloudinary: { url: '/f_auto,q_auto,w_200,h_200/test' },
twicpics: { url: '/test.png?twic=v1/cover=200x200' },
fastly: { url: '/test.png?width=200&height=200' },
Expand All @@ -74,6 +78,7 @@ export const images = [
{
args: ['/test.png', { width: 200, height: 200, fit: 'contain' }],
ipx: { url: '/_ipx/fit_contain,s_200x200/test.png' },
cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain/test.png' },
cloudinary: { url: '/f_auto,q_auto,w_200,h_200,c_scale/test' },
twicpics: { url: '/test.png?twic=v1/inside=200x200' },
fastly: { url: '/test.png?width=200&height=200&fit=bounds' },
Expand All @@ -92,6 +97,7 @@ export const images = [
{
args: ['/test.png', { width: 200, height: 200, fit: 'contain', format: 'jpeg' }],
ipx: { url: '/_ipx/fit_contain,f_jpeg,s_200x200/test.png' },
cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain,f=jpeg/test.png' },
cloudinary: { url: '/f_jpg,q_auto,w_200,h_200,c_scale/test' },
twicpics: { url: '/test.png?twic=v1/output=jpeg/inside=200x200' },
fastly: { url: '/test.png?width=200&height=200&fit=bounds&format=jpeg' },
Expand Down
12 changes: 12 additions & 0 deletions test/unit/providers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { images } from '../providers'

import { cleanDoubleSlashes } from '~/runtime/utils'
import * as ipx from '~/runtime/providers/ipx'
import * as cloudflare from '~/runtime/providers/cloudflare'
import * as cloudinary from '~/runtime/providers/cloudinary'
import * as twicpics from '~/runtime/providers/twicpics'
import * as fastly from '~/runtime/providers/fastly'
Expand Down Expand Up @@ -42,6 +43,17 @@ describe('Providers', () => {
})
})

test('cloudflare', () => {
const providerOptions = {
baseURL: '/'
}
for (const image of images) {
const [src, modifiers] = image.args
const generated = cloudflare.getImage(src, { modifiers, ...providerOptions }, emptyContext)
expect(generated).toMatchObject(image.cloudflare)
}
})

test('cloudinary', () => {
const providerOptions = {
baseURL: '/'
Expand Down

0 comments on commit 59ac32c

Please sign in to comment.