diff --git a/docs/content/en/4.providers/gumlet.md b/docs/content/en/4.providers/gumlet.md new file mode 100644 index 000000000..fc8e156fd --- /dev/null +++ b/docs/content/en/4.providers/gumlet.md @@ -0,0 +1,49 @@ +--- +title: Gumlet Provider +description: 'Nuxt Image has first class integration with Gumlet' +navigation: + title: Gumlet +--- + +Integration between [Gumlet](https://docs.gumlet.com/) and the image module. + +To use this provider you just need to specify the base url of your service in Gumlet. + +```js{}[nuxt.config.js] +export default { + image: { + gumlet: { + baseURL: 'https://demo.gumlet.io' + } + } +} +``` + +## gumlet `mode` values + +Gumlet supports all the [the standard values for `fit` property](/components/nuxt-img#fit) of Nuxt image and Nuxt picture. + + +## gumlet modifiers + +Beside the [standard modifiers](/components/nuxt-img#modifiers), you can also pass all gumlet-specific render API parameters to the `modifiers` prop. + +For a full list of these modifiers and their uses, check out [Gumlet's image Rendering API documentation](https://docs.gumlet.com/reference/image-transform-size#mode). + +## gumlet best practices + +Some common best practices when using Gumlet, would be to include our `format=auto` parameter, which will automatically apply the best format for an image and compress the image as well. Combine this with some top of intelligent cropping and resizing and you will have a great image! + +```html + +``` + +This will return a 300 x 500 image, which has been compressed, will display next-gen formats for a browser, and has been cropped intelligently to the face of the [woman in the hat](https://demo.gumlet.io/sea.jpeg?format=auto&w=300&h=500&compress=true). + diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index fd335051c..ca0d6686c 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -42,6 +42,9 @@ export default { glide: { baseURL: 'https://glide.herokuapp.com/1.0/' }, + gumlet: { + baseURL: 'https://demo.gumlet.io' + }, imgix: { baseURL: 'https://assets.imgix.net' }, diff --git a/playground/providers.ts b/playground/providers.ts index 38120bab5..7148484ad 100644 --- a/playground/providers.ts +++ b/playground/providers.ts @@ -135,6 +135,18 @@ export const providers: Provider[] = [ } ] }, + // gumlet + { + name: 'gumlet', + samples: [ + { + src: '/sea.jpeg', + width: 300, + height: 300, + fit: 'cover' + } + ] + }, // imgix { name: 'imgix', diff --git a/src/provider.ts b/src/provider.ts index 45938090f..d464a631b 100644 --- a/src/provider.ts +++ b/src/provider.ts @@ -10,6 +10,7 @@ const BuiltInProviders = [ 'fastly', 'glide', 'imagekit', + 'gumlet', 'imgix', 'ipx', 'netlify', diff --git a/src/runtime/providers/gumlet.ts b/src/runtime/providers/gumlet.ts new file mode 100644 index 000000000..820f35a45 --- /dev/null +++ b/src/runtime/providers/gumlet.ts @@ -0,0 +1,78 @@ +import { joinURL } from 'ufo' +import type { ProviderGetImage } from 'src' +import { createOperationsGenerator } from '~image' + +export const operationsGenerator = createOperationsGenerator({ + keyMap: { + width: 'w', + height: 'h', + format: 'format', + quality: 'q', + backgroundColor: 'bg', + rotate: 'rot', + mask: 'mask', + auto: 'auto', + crop: 'crop', + brightness: 'bri', + contrast: 'con', + exposure: 'exp', + gamma: 'gam', + highlight: 'high', + hueShift: 'hue', + invert: 'invert', + saturation: 'sat', + sharpen: 'sharp', + padding: 'pad', + paletteColorCount: 'colors', + colorPaletteExtraction: 'palette', + cssPrefix: 'prefix', + jsonFaceData: 'faces', + fillMode: 'fill', + fillColor: 'fill-color', + transparency: 'transparency', + focalPointDebug: 'fp-debug', + focalPointXPosition: 'fp-x', + focalPointYPosition: 'fp-y', + focalPointZoom: 'fp-z', + chromaSubsampling: 'chromasub', + colorQuantization: 'colorquant', + colorSpace: 'colorspace', + dotsPerInch: 'dpi', + pdfPageNumber: 'page', + pixelDensity: 'dpr', + aspectRatio: 'ar', + sourceRectangleRegion: 'rect', + monochrome: 'monochrome' + }, + valueMap: { + fit: { + fill: 'scale', + inside: 'max', + outside: 'min', + cover: 'crop', + contain: 'fill', + clamp: 'clamp', + clip: 'clip', + facearea: 'facearea', + fillMax: 'fillmax' + }, + format: { + gif: 'gif', + jpg: 'jpg', + json: 'json', + png: 'png', + avif: 'avif', + webp: 'webp', + auto: 'auto' + } + }, + joinWith: '&', + formatter: (key, value) => `${key}=${value}` +}) + +export const getImage: ProviderGetImage = (src, { modifiers = {}, baseURL = '/' } = {}) => { + const operations = operationsGenerator(modifiers) + return { + url: joinURL(baseURL, src + (operations ? ('?' + operations) : '')) + } +} diff --git a/src/types/module.ts b/src/types/module.ts index b658967bf..30880e8f3 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -17,6 +17,7 @@ export interface ImageProviders { contentful?: any fastly?: any glide?: any + gumlet?: any imagekit?: any imgix?: any prismic?: any diff --git a/test/providers.ts b/test/providers.ts index 8f809bf31..c33a7ede1 100644 --- a/test/providers.ts +++ b/test/providers.ts @@ -6,6 +6,7 @@ export const images = [ twicpics: { url: '/test.png' }, fastly: { url: '/test.png' }, glide: { url: '/test.png' }, + gumlet: { url: '/test.png' }, imgix: { url: '/test.png' }, imageengine: { url: '/test.png' }, unsplash: { url: '/test.png' }, @@ -22,6 +23,7 @@ export const images = [ twicpics: { url: '/test.png?twic=v1/cover=200x-' }, fastly: { url: '/test.png?width=200' }, glide: { url: '/test.png?w=200' }, + gumlet: { url: '/test.png?w=200' }, imgix: { url: '/test.png?w=200' }, imageengine: { url: '/test.png?imgeng=/w_200' }, unsplash: { url: '/test.png?w=200' }, @@ -38,6 +40,7 @@ export const images = [ twicpics: { url: '/test.png?twic=v1/cover=-x200' }, fastly: { url: '/test.png?height=200' }, glide: { url: '/test.png?h=200' }, + gumlet: { url: '/test.png?h=200' }, imgix: { url: '/test.png?h=200' }, imageengine: { url: '/test.png?imgeng=/h_200' }, unsplash: { url: '/test.png?h=200' }, @@ -54,6 +57,7 @@ export const images = [ twicpics: { url: '/test.png?twic=v1/cover=200x200' }, fastly: { url: '/test.png?width=200&height=200' }, glide: { url: '/test.png?w=200&h=200' }, + gumlet: { url: '/test.png?w=200&h=200' }, imgix: { url: '/test.png?w=200&h=200' }, imageengine: { url: '/test.png?imgeng=/w_200/h_200' }, unsplash: { url: '/test.png?w=200&h=200' }, @@ -70,6 +74,7 @@ export const images = [ twicpics: { url: '/test.png?twic=v1/contain=200x200' }, fastly: { url: '/test.png?width=200&height=200&fit=bounds' }, glide: { url: '/test.png?w=200&h=200&fit=contain' }, + gumlet: { url: '/test.png?w=200&h=200&fit=fill' }, imgix: { url: '/test.png?w=200&h=200&fit=fill' }, imageengine: { url: '/test.png?imgeng=/w_200/h_200/m_letterbox' }, unsplash: { url: '/test.png?w=200&h=200&fit=fill' }, @@ -86,6 +91,7 @@ export const images = [ twicpics: { url: '/test.png?twic=v1/output=jpeg/contain=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' }, + gumlet: { url: '/test.png?w=200&h=200&fit=fill&format=jpeg' }, imgix: { url: '/test.png?w=200&h=200&fit=fill&fm=jpeg' }, imageengine: { url: '/test.png?imgeng=/w_200/h_200/m_letterbox/f_jpg' }, unsplash: { url: '/test.png?w=200&h=200&fit=fill&fm=jpeg' }, diff --git a/test/unit/providers.test.ts b/test/unit/providers.test.ts index f87e71cec..fda5be74d 100644 --- a/test/unit/providers.test.ts +++ b/test/unit/providers.test.ts @@ -7,6 +7,7 @@ import * as twicpics from '~/runtime/providers/twicpics' import * as fastly from '~/runtime/providers/fastly' import * as glide from '~/runtime/providers/glide' import * as imgix from '~/runtime/providers/imgix' +import * as gumlet from '~/runtime/providers/gumlet' import * as imageengine from '~/runtime/providers/imageengine' import * as unsplash from '~/runtime/providers/unsplash' import * as imagekit from '~/runtime/providers/imagekit' @@ -126,6 +127,18 @@ describe('Providers', () => { } }) + test('gumlet', () => { + const providerOptions = { + baseURL: '' + } + + for (const image of images) { + const [src, modifiers] = image.args + const generated = gumlet.getImage(src, { modifiers, ...providerOptions }, emptyContext) + expect(generated).toMatchObject(image.gumlet) + } + }) + test('imgix', () => { const providerOptions = { baseURL: ''