diff --git a/docs/content/4.providers/directus.md b/docs/content/4.providers/directus.md new file mode 100644 index 000000000..70bddb681 --- /dev/null +++ b/docs/content/4.providers/directus.md @@ -0,0 +1,19 @@ +--- +title: Directus +description: Nuxt Image has first class integration with Directus +--- + +Integration between [Directus](https://docs.directus.io/reference/files/#requesting-a-thumbnail) and the image module. + +To use this provider you need to specify the base url of your service in Directus. + +```js{}[nuxt.config.js] +export default { + image: { + directus: { + // baseURL of your Directus application + baseURL: 'https://demo.directus.io' + } + } +} +``` diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index 30c741c3d..56f9ae15c 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -73,6 +73,9 @@ export default { vercel: { baseURL: 'https://image-component.nextjs.gallery/_next/image' }, + directus: { + baseURL: 'https://cms.developling.nl' + }, imageengine: { baseURL: 'https://abc123.imgeng.in' }, diff --git a/playground/providers.ts b/playground/providers.ts index c3f827b04..c482787f8 100644 --- a/playground/providers.ts +++ b/playground/providers.ts @@ -124,6 +124,29 @@ export const providers: Provider[] = [ } ] }, + // Directus + { + name: 'directus', + samples: [ + { + src: 'c0c8a61c-d69e-4dc8-b403-1426d9bded48', + width: 100, + height: 100, + fit: 'contain' + }, + { + src: 'c0c8a61c-d69e-4dc8-b403-1426d9bded48', + transforms: [['blur', 45], + ['tint', 'rgb(255, 0, 0)'], + ['expand', { right: 200, bottom: 150 }] + ] + }, + { + src: 'c0c8a61c-d69e-4dc8-b403-1426d9bded48', + key: 'test-preset' + } + ] + }, // Fastly { name: 'fastly', diff --git a/src/provider.ts b/src/provider.ts index 73893b5d2..1227672a8 100644 --- a/src/provider.ts +++ b/src/provider.ts @@ -9,6 +9,7 @@ const BuiltInProviders = [ 'cloudinary', 'contentful', 'cloudimage', + 'directus', 'fastly', 'glide', 'imagekit', diff --git a/src/runtime/providers/directus.ts b/src/runtime/providers/directus.ts new file mode 100644 index 000000000..cac0ecaa5 --- /dev/null +++ b/src/runtime/providers/directus.ts @@ -0,0 +1,38 @@ +// https://docs.directus.io/reference/files/#requesting-a-thumbnail + +import { joinURL, encodeQueryItem, encodePath, withBase } from 'ufo' +import { ProviderGetImage } from 'src' +import { createOperationsGenerator } from '~image' + +const operationsGenerator = createOperationsGenerator({ + keyMap: { + width: 'width', + height: 'height', + fit: 'fit', + format: 'format', + quality: 'quality', + withoutEnlargement: 'withoutEnlargement', + transforms: 'transforms' + }, + valueMap: { + fit: { + inside: 'inside', + outside: 'outside', + cover: 'cover', + contain: 'contain' + }, + format: { + jpeg: 'jpg' + } + }, + joinWith: '&', + formatter: (key, val) => encodeQueryItem(key, val) +}) + +export const getImage: ProviderGetImage = (src, { modifiers = {}, baseURL = '/' } = {}) => { + const params = operationsGenerator(modifiers) + + return { + url: withBase(joinURL('/assets/', encodePath(src) + (params ? '?' + params : '')), baseURL) + } +} diff --git a/src/types/module.ts b/src/types/module.ts index 3521a08a5..1d9df2727 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -44,6 +44,7 @@ export interface ImageProviders { cloudinary?: Partial contentful?: any cloudimage?: any + directus?: any fastly?: any glide?: any gumlet?: any diff --git a/test/providers.ts b/test/providers.ts index 9cc0d4208..81c57e57e 100644 --- a/test/providers.ts +++ b/test/providers.ts @@ -4,6 +4,7 @@ export const images = [ ipx: { url: '/_ipx/_/test.png' }, cloudflare: { url: '/test.png' }, cloudinary: { url: '/f_auto,q_auto/test' }, + directus: { url: '/assets/test.png' }, twicpics: { url: '/test.png' }, fastly: { url: '/test.png' }, glide: { url: '/test.png' }, @@ -23,6 +24,7 @@ export const images = [ 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' }, + directus: { url: '/assets/test.png?width=200' }, twicpics: { url: '/test.png?twic=v1/cover=200x-' }, fastly: { url: '/test.png?width=200' }, glide: { url: '/test.png?w=200' }, @@ -42,6 +44,7 @@ export const images = [ 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' }, + directus: { url: '/assets/test.png?height=200' }, twicpics: { url: '/test.png?twic=v1/cover=-x200' }, fastly: { url: '/test.png?height=200' }, glide: { url: '/test.png?h=200' }, @@ -61,6 +64,7 @@ export const images = [ 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' }, + directus: { url: '/assets/test.png?width=200&height=200' }, twicpics: { url: '/test.png?twic=v1/cover=200x200' }, fastly: { url: '/test.png?width=200&height=200' }, glide: { url: '/test.png?w=200&h=200' }, @@ -80,6 +84,7 @@ export const images = [ 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' }, + directus: { url: '/assets/test.png?width=200&height=200&fit=contain' }, twicpics: { url: '/test.png?twic=v1/inside=200x200' }, fastly: { url: '/test.png?width=200&height=200&fit=bounds' }, glide: { url: '/test.png?w=200&h=200&fit=contain' }, @@ -99,6 +104,7 @@ export const images = [ 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' }, + directus: { url: '/assets/test.png?width=200&height=200&fit=contain&format=jpg' }, twicpics: { url: '/test.png?twic=v1/output=jpeg/inside=200x200' }, fastly: { url: '/test.png?width=200&height=200&fit=bounds&format=jpeg' }, glide: { url: '/test.png?w=200&h=200&fit=contain&fm=jpeg' }, diff --git a/test/unit/providers.test.ts b/test/unit/providers.test.ts index 1b1f7c8aa..b584e9ba7 100644 --- a/test/unit/providers.test.ts +++ b/test/unit/providers.test.ts @@ -4,6 +4,7 @@ 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 directus from '~/runtime/providers/directus' import * as twicpics from '~/runtime/providers/twicpics' import * as fastly from '~/runtime/providers/fastly' import * as glide from '~/runtime/providers/glide' @@ -106,6 +107,18 @@ describe('Providers', () => { }) }) + test('directus', () => { + const providerOptions = { + baseURL: '/' + } + + for (const image of images) { + const [src, modifiers] = image.args + const generated = directus.getImage(src, { modifiers, ...providerOptions }, emptyContext) + expect(generated).toMatchObject(image.directus) + } + }) + test('twicpics', () => { const providerOptions = { baseURL: ''