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: ''