Skip to content

Commit 94625ce

Browse files
shadow81627pi0
andcommitted
feat: cloudflare provider (#359)
Co-authored-by: pooya parsa <[email protected]>
1 parent 8601e61 commit 94625ce

File tree

8 files changed

+121
-0
lines changed

8 files changed

+121
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: Cloudflare Provider
3+
description: 'Nuxt Image has first class integration with Cloudflare'
4+
navigation:
5+
title: Cloudflare
6+
---
7+
8+
Integration between [Cloudflare](https://developers.cloudflare.com/images/) and the image module.
9+
10+
:::alert{type="info"}
11+
Availability only for Business and Enterprise Customers. Normally Cloudflare [pages](https://pages.cloudflare.com/) users can already benefit from build-time image optimization.
12+
:::
13+
14+
To use this provider you just need to specify the base url (zone) of your service:
15+
16+
```js{}[nuxt.config.js]
17+
export default {
18+
image: {
19+
baseURL: 'https://that-test.site'
20+
}
21+
}
22+
```
23+
24+
**Example:**
25+
26+
```vue
27+
<nuxt-img provider="cloudflare" src="/burger.jpeg" height="300" :modifiers="{ fit: 'contain' }" />
28+
```
29+
30+
## Options
31+
32+
### `baseURL`
33+
34+
Default: `/`
35+
36+
Your deployment's domain (zone).
37+
38+
**Note:** `/cdn-cgi/image/` will be automatically appended for generating URLs.

playground/nuxt.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export default <NuxtConfig> {
3232
storyblok: {
3333
baseURL: 'https://a.storyblok.com/'
3434
},
35+
cloudflare: {
36+
baseURL: 'https://that-test.site'
37+
},
3538
cloudinary: {
3639
baseURL: 'https://res.cloudinary.com/nuxt/image/upload/'
3740
},

playground/providers.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ export const providers: Provider[] = [
4545
}
4646
]
4747
},
48+
// Cloudflare
49+
{
50+
name: 'cloudflare',
51+
samples: [
52+
{
53+
src: 'https://s3.that-test.site/burger.jpeg',
54+
height: 300,
55+
fit: 'contain'
56+
}
57+
]
58+
},
4859
// Cloudinary
4960
{
5061
name: 'cloudinary',

src/provider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { ModuleOptions, InputProvider, ImageModuleProvider, ProviderSetup }
55
import { ipxSetup } from './ipx'
66

77
const BuiltInProviders = [
8+
'cloudflare',
89
'cloudinary',
910
'contentful',
1011
'cloudimage',
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { joinURL, encodeQueryItem } from 'ufo'
2+
import { ProviderGetImage } from 'src'
3+
import { createOperationsGenerator } from '~image'
4+
5+
const operationsGenerator = createOperationsGenerator({
6+
keyMap: {
7+
width: 'w',
8+
height: 'h',
9+
dpr: 'dpr',
10+
fit: 'fit',
11+
gravity: 'g',
12+
quality: 'q',
13+
format: 'f',
14+
sharpen: 'sharpen'
15+
},
16+
valueMap: {
17+
fit: {
18+
cover: 'cover',
19+
contain: 'contain',
20+
fill: 'scale-down',
21+
outside: 'crop',
22+
inside: 'pad'
23+
},
24+
gravity: {
25+
auto: 'auto',
26+
side: 'side'
27+
}
28+
},
29+
joinWith: ',',
30+
formatter: (key, val) => encodeQueryItem(key, val)
31+
})
32+
33+
const defaultModifiers = {}
34+
35+
// https://developers.cloudflare.com/images/image-resizing/url-format/
36+
export const getImage: ProviderGetImage = (src, {
37+
modifiers = {},
38+
baseURL = '/'
39+
} = {}) => {
40+
const mergeModifiers = { ...defaultModifiers, ...modifiers }
41+
const operations = operationsGenerator(mergeModifiers as any)
42+
43+
// https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>
44+
const url = operations ? joinURL(baseURL, 'cdn-cgi/image', operations, src) : joinURL(baseURL, src)
45+
46+
return {
47+
url
48+
}
49+
}

src/types/module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export interface CloudinaryOptions {
4040
}
4141

4242
export interface ImageProviders {
43+
cloudflare?: any
4344
cloudinary?: Partial<CloudinaryOptions>
4445
contentful?: any
4546
cloudimage?: any

test/providers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const images = [
22
{
33
args: ['/test.png', {}],
44
ipx: { url: '/_ipx/_/test.png' },
5+
cloudflare: { url: '/test.png' },
56
cloudinary: { url: '/f_auto,q_auto/test' },
67
twicpics: { url: '/test.png' },
78
fastly: { url: '/test.png' },
@@ -20,6 +21,7 @@ export const images = [
2021
{
2122
args: ['/test.png', { width: 200 }],
2223
ipx: { url: '/_ipx/w_200/test.png' },
24+
cloudflare: { url: '/cdn-cgi/image/w=200/test.png' },
2325
cloudinary: { url: '/f_auto,q_auto,w_200/test' },
2426
twicpics: { url: '/test.png?twic=v1/cover=200x-' },
2527
fastly: { url: '/test.png?width=200' },
@@ -38,6 +40,7 @@ export const images = [
3840
{
3941
args: ['/test.png', { height: 200 }],
4042
ipx: { url: '/_ipx/h_200/test.png' },
43+
cloudflare: { url: '/cdn-cgi/image/h=200/test.png' },
4144
cloudinary: { url: '/f_auto,q_auto,h_200/test' },
4245
twicpics: { url: '/test.png?twic=v1/cover=-x200' },
4346
fastly: { url: '/test.png?height=200' },
@@ -56,6 +59,7 @@ export const images = [
5659
{
5760
args: ['/test.png', { width: 200, height: 200 }],
5861
ipx: { url: '/_ipx/s_200x200/test.png' },
62+
cloudflare: { url: '/cdn-cgi/image/w=200,h=200/test.png' },
5963
cloudinary: { url: '/f_auto,q_auto,w_200,h_200/test' },
6064
twicpics: { url: '/test.png?twic=v1/cover=200x200' },
6165
fastly: { url: '/test.png?width=200&height=200' },
@@ -74,6 +78,7 @@ export const images = [
7478
{
7579
args: ['/test.png', { width: 200, height: 200, fit: 'contain' }],
7680
ipx: { url: '/_ipx/fit_contain,s_200x200/test.png' },
81+
cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain/test.png' },
7782
cloudinary: { url: '/f_auto,q_auto,w_200,h_200,c_scale/test' },
7883
twicpics: { url: '/test.png?twic=v1/inside=200x200' },
7984
fastly: { url: '/test.png?width=200&height=200&fit=bounds' },
@@ -92,6 +97,7 @@ export const images = [
9297
{
9398
args: ['/test.png', { width: 200, height: 200, fit: 'contain', format: 'jpeg' }],
9499
ipx: { url: '/_ipx/fit_contain,f_jpeg,s_200x200/test.png' },
100+
cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain,f=jpeg/test.png' },
95101
cloudinary: { url: '/f_jpg,q_auto,w_200,h_200,c_scale/test' },
96102
twicpics: { url: '/test.png?twic=v1/output=jpeg/inside=200x200' },
97103
fastly: { url: '/test.png?width=200&height=200&fit=bounds&format=jpeg' },

test/unit/providers.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { images } from '../providers'
22

33
import { cleanDoubleSlashes } from '~/runtime/utils'
44
import * as ipx from '~/runtime/providers/ipx'
5+
import * as cloudflare from '~/runtime/providers/cloudflare'
56
import * as cloudinary from '~/runtime/providers/cloudinary'
67
import * as twicpics from '~/runtime/providers/twicpics'
78
import * as fastly from '~/runtime/providers/fastly'
@@ -42,6 +43,17 @@ describe('Providers', () => {
4243
})
4344
})
4445

46+
test('cloudflare', () => {
47+
const providerOptions = {
48+
baseURL: '/'
49+
}
50+
for (const image of images) {
51+
const [src, modifiers] = image.args
52+
const generated = cloudflare.getImage(src, { modifiers, ...providerOptions }, emptyContext)
53+
expect(generated).toMatchObject(image.cloudflare)
54+
}
55+
})
56+
4557
test('cloudinary', () => {
4658
const providerOptions = {
4759
baseURL: '/'

0 commit comments

Comments
 (0)