Skip to content

Commit

Permalink
feat: cloudimage provider (#523)
Browse files Browse the repository at this point in the history
Co-authored-by: Amr Hamdy <amrhamdy@outlook.com>
  • Loading branch information
pi0 and Amr Hamdy committed Jun 21, 2022
1 parent 79c1580 commit 33b36bc
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 6 deletions.
75 changes: 75 additions & 0 deletions docs/content/en/4.providers/cloudimage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
title: Cloudimage Provider
description: 'Nuxt Image has first class integration with Cloudimage'
navigation:
title: Cloudimage
---

Integration between [Cloudimage](https://www.cloudimage.io/en/home) and the image module.

To use this provider you just need to specify the token of your project in cloudimage.

```js{}[nuxt.config.js]
export default {
image: {
cloudimage: {
token: 'demo'
}
}
}
```

**Note:** Current integration uses API `v7`.

## Options

You can override default options:

### `token`

- Type: **String** (required)
- Default: `demo`

Your Cloudimage customer token. [register](https://www.cloudimage.io/en/register_page) for a Cloudimage account to get one. The subscription takes less than a minute and is totally free.

### `baseURL`

- Type: **String**

Your uploads base URL. This alows to shorten your origin image URLs.

```js{}[nuxt.config.js]
export default {
image: {
cloudimage: {
token: 'demo',
baseURL: 'sample.li' // optional
}
}
}
```

### `cdnURL`

- Type: **String**
- Default: `https://{token}.cloudimg.io/v7`

## Cloudimage modifiers

Beside the [standard modifiers](/components/nuxt-img#modifiers), also you can pass Cloudimage-specific [Cloudimage-specific transformation](https://docs.cloudimage.io/go/cloudimage-documentation-v7/en/introduction) params to `modifiers` prop.

## Cloudimage `fit` values

Beside [the standard values for `fit` property](/components/nuxt-img#fit) of Nuxt image and Nuxt picture, Cloudimage offers the following for extra resizing params:

* `crop` - Crops the image to specified dimensions (width and height) and keeps proportions.

* `face` - Crops the image automatically keeping the most prominent face.

* `fit` - Resizes the image to fit into a specified width and height box, adds padding (image or solid colour) to keep proportions.

* `cropfit` - Sets crop or fit resize mode depending on the origin and the desired dimensions.

* `bound` - Resizes to a given width and height box and keeps proportions. Similar to fit but without adding padding.

* `boundmin` - Resizes an image while bounding the smaller dimension to the desired width or height while keeping proportions.
4 changes: 4 additions & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export default <NuxtConfig> {
baseURL: 'https://res.cloudinary.com/nuxt/image/upload/'
},
contentful: {},
cloudimage: {
token: 'demo',
baseURL: 'sample.li'
},
fastly: {
baseURL: 'https://www.fastly.io'
},
Expand Down
26 changes: 26 additions & 0 deletions playground/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,32 @@ export const providers: Provider[] = [
}
]
},
// Cloudimage
{
name: 'cloudimage',
samples: [
{
src: 'bag.jpg',
width: 500,
height: 500,
fit: 'contain'
},
{
src: 'boat.jpg',
width: 800,
height: 800,
quality: 75,
fit: 'cover'
},
{
src: 'img.jpg',
width: 300,
height: 300,
format: 'webp',
fit: 'fill'
}
]
},
// Fastly
{
name: 'fastly',
Expand Down
1 change: 1 addition & 0 deletions src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ipxSetup } from './ipx'
const BuiltInProviders = [
'cloudinary',
'contentful',
'cloudimage',
'fastly',
'glide',
'imagekit',
Expand Down
38 changes: 38 additions & 0 deletions src/runtime/providers/cloudimage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { joinURL } from 'ufo'
import type { ProviderGetImage } from 'src'
import { createOperationsGenerator } from '~image'

const operationsGenerator = createOperationsGenerator({
keyMap: {
fit: 'func',
quality: 'q',
format: 'force_format'
},
valueMap: {
fit: {
cover: 'crop',
contain: 'fit',
fill: 'cover',
inside: 'bound',
outside: 'boundmin'
}
},
joinWith: '&',
formatter: (key, value) => `${key}=${value}`
})

// https://docs.cloudimage.io/go/cloudimage-documentation-v7/en/introduction
export const getImage: ProviderGetImage = (src, {
modifiers = {},
baseURL = '',
token = 'demo',
cdnURL = ''
} = {}) => {
const operations = operationsGenerator(modifiers)
if (!cdnURL) {
cdnURL = `https://${token}.cloudimg.io/v7`
}
return {
url: joinURL(cdnURL, baseURL, src) + (operations ? ('?' + operations) : '')
}
}
1 change: 1 addition & 0 deletions src/types/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface CloudinaryOptions {
export interface ImageProviders {
cloudinary?: Partial<CloudinaryOptions>
contentful?: any
cloudimage?: any
fastly?: any
glide?: any
gumlet?: any
Expand Down
18 changes: 12 additions & 6 deletions test/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export const images = [
netlify: { url: '/test.png' },
prismic: { url: '/test.png?auto=compress,format&rect=0,0,200,200&w=100&h=100' },
sanity: { url: 'https://cdn.sanity.io/images/projectid/production/test-300x450.png?auto=format' },
contentful: { url: '/test.png' }
contentful: { url: '/test.png' },
cloudimage: { url: 'https://demo.cloudimg.io/v7/test.png' }
},
{
args: ['/test.png', { width: 200 }],
Expand All @@ -31,7 +32,8 @@ export const images = [
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' },
sanity: { url: 'https://cdn.sanity.io/images/projectid/production/test-300x450.png?w=200&auto=format' },
contentful: { url: '/test.png?w=200' }
contentful: { url: '/test.png?w=200' },
cloudimage: { url: 'https://demo.cloudimg.io/v7/test.png?width=200' }
},
{
args: ['/test.png', { height: 200 }],
Expand All @@ -48,7 +50,8 @@ export const images = [
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' },
sanity: { url: 'https://cdn.sanity.io/images/projectid/production/test-300x450.png?h=200&auto=format' },
contentful: { url: '/test.png?h=200' }
contentful: { url: '/test.png?h=200' },
cloudimage: { url: 'https://demo.cloudimg.io/v7/test.png?height=200' }
},
{
args: ['/test.png', { width: 200, height: 200 }],
Expand All @@ -65,7 +68,8 @@ export const images = [
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' },
sanity: { url: 'https://cdn.sanity.io/images/projectid/production/test-300x450.png?w=200&h=200&auto=format' },
contentful: { url: '/test.png?w=200&h=200' }
contentful: { url: '/test.png?w=200&h=200' },
cloudimage: { url: 'https://demo.cloudimg.io/v7/test.png?width=200&height=200' }
},
{
args: ['/test.png', { width: 200, height: 200, fit: 'contain' }],
Expand All @@ -82,7 +86,8 @@ export const images = [
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' },
sanity: { url: 'https://cdn.sanity.io/images/projectid/production/test-300x450.png?w=200&h=200&fit=fill&auto=format&bg=ffffff' },
contentful: { url: '/test.png?w=200&h=200&fit=fill' }
contentful: { url: '/test.png?w=200&h=200&fit=fill' },
cloudimage: { url: 'https://demo.cloudimg.io/v7/test.png?width=200&height=200&func=fit' }
},
{
args: ['/test.png', { width: 200, height: 200, fit: 'contain', format: 'jpeg' }],
Expand All @@ -99,7 +104,8 @@ export const images = [
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' },
sanity: { url: 'https://cdn.sanity.io/images/projectid/production/test-300x450.png?w=200&h=200&fit=fill&fm=jpg&bg=ffffff' },
contentful: { url: '/test.png?w=200&h=200&fit=fill&fm=jpg' }
contentful: { url: '/test.png?w=200&h=200&fit=fill&fm=jpg' },
cloudimage: { url: 'https://demo.cloudimg.io/v7/test.png?width=200&height=200&func=fit&force_format=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 @@ -15,6 +15,7 @@ import * as netlify from '~/runtime/providers/netlify'
import * as prismic from '~/runtime/providers/prismic'
import * as sanity from '~/runtime/providers/sanity'
import * as contentful from '~/runtime/providers/contentful'
import * as cloudimage from '~/runtime/providers/cloudimage'

const emptyContext = { options: {} } as any

Expand Down Expand Up @@ -257,4 +258,16 @@ describe('Providers', () => {
expect(generated).toMatchObject(image.contentful)
}
})

test('cloudimage', () => {
const providerOptions = {
token: 'demo'
}

for (const image of images) {
const [src, modifiers] = image.args
const generated = cloudimage.getImage(src, { modifiers, ...providerOptions }, emptyContext)
expect(generated).toMatchObject(image.cloudimage)
}
})
})

0 comments on commit 33b36bc

Please sign in to comment.