Repository: nuxt/image (ts)

Issue:
Add all image options for amplify
Currently, the amplify image provider doesn't pass in options like height, format, fit, etc. as seen [here](https://docs.aws.amazon.com/amplify/latest/userguide/integrate-image-optimization-framework.html#uri-request-parameters). It would be good to have this implemented to enable more cross-compatibility.

Pull request:
feat(amplify): added additional modifiers
### 🔗 Linked issue

resolves #1655

### ❓ Type of change

<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. -->

- [x] 📖 Documentation (updates to the documentation or readme)
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [x] 👌 Enhancement (improving an existing functionality)
- [ ] ✨ New feature (a non-breaking change that adds functionality)
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

### 📚 Description

This just makes it possible to pass in all of the currently available options into the aws provider.

Patch:
diff --git a/docs/content/3.providers/aws-amplify.md b/docs/content/3.providers/aws-amplify.md
index 63ac246..5f223db 100644
--- a/docs/content/3.providers/aws-amplify.md
+++ b/docs/content/3.providers/aws-amplify.md
@@ -50,3 +50,17 @@ export default {
   }
 }
 ```
+
+## Modifiers
+
+All the default modifiers from [AWS's documentation](https://docs.aws.amazon.com/amplify/latest/userguide/integrate-image-optimization-framework.html#uri-request-parameters) are available.
+
+```vue
+<NuxtImg
+  src="/test.jpg"
+  height="512"
+  width="512"
+  :modifiers="{ flip: true }"
+  :quality="90"
+/>
+```
diff --git a/src/runtime/providers/awsAmplify.ts b/src/runtime/providers/awsAmplify.ts
index eb5f668..6979dac 100644
--- a/src/runtime/providers/awsAmplify.ts
+++ b/src/runtime/providers/awsAmplify.ts
@@ -1,5 +1,54 @@
-import { stringifyQuery } from 'ufo'
+import { encodeQueryItem, joinURL } from 'ufo'
 import type { ProviderGetImage } from '../../module'
+import { createOperationsGenerator } from '#image'
+
+export const operationsGenerator = createOperationsGenerator({
+  keyMap: {
+    width: 'w',
+    height: 'h',
+    quality: 'q',
+    trim: 'trim',
+    extend: 'extend',
+    extract: 'extract',
+    rotate: 'rotate',
+    flip: 'flip',
+    flop: 'flop',
+    sharpen: 'sharpen',
+    median: 'median',
+    blur: 'blur',
+    gamma: 'gamma',
+    negate: 'negate',
+    normalize: 'normalize',
+    threshold: 'threshold',
+    tint: 'tint',
+    grayscale: 'grayscale',
+  },
+  valueMap: {
+    format: {
+      jpg: 'jpeg',
+      jpeg: 'jpeg',
+      webp: 'webp',
+      avif: 'avif',
+      png: 'png',
+    },
+    fit: {
+      cover: 'cover',
+      contain: 'contain',
+      fill: 'fill',
+      inside: 'inside',
+      outside: 'outside',
+    },
+    position: {
+      center: 'center',
+      top: 'top',
+      right: 'right',
+      bottom: 'bottom',
+      left: 'left',
+    },
+  },
+  joinWith: '&',
+  formatter: (key, value) => `${key}=${value}`,
+})
 
 export const getImage: ProviderGetImage = (src, { modifiers, baseURL = '/_amplify/image' } = {}, ctx) => {
   const validWidths = Object.values(ctx.options.screens || {}).sort((a, b) => a - b)
@@ -23,12 +72,14 @@ export const getImage: ProviderGetImage = (src, { modifiers, baseURL = '/_amplif
     return { url: src }
   }
 
+  const operations = operationsGenerator({
+    ...modifiers,
+    width: String(width),
+    quality: String(modifiers?.quality || '100'),
+  } as any)
+
   return {
-    url: baseURL + '?' + stringifyQuery({
-      url: src,
-      w: String(width),
-      q: String(modifiers?.quality || '100'),
-    }),
+    url: joinURL(baseURL + `?${encodeQueryItem('url', src)}` + (operations ? `&${operations}` : '')),
   }
 }
 


Test patch:
diff --git a/test/providers.ts b/test/providers.ts
index 25b0369..03c666e 100644
--- a/test/providers.ts
+++ b/test/providers.ts
@@ -76,7 +76,7 @@ export const images = [
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/h_200/test.png' },
     aliyun: { url: '/test.png?image_process=resize,h_200' },
-    awsAmplify: { url: '/?url=%2Ftest.png&w=1536&q=100' },
+    awsAmplify: { url: '/?url=%2Ftest.png&h=200&w=1536&q=100' },
     cloudflare: { url: '/cdn-cgi/image/h=200/test.png' },
     cloudinary: { url: '/f_auto,q_auto,h_200/test' },
     twicpics: { url: '/test.png?twic=v1/cover=-x200' },
@@ -112,7 +112,7 @@ export const images = [
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/s_200x200/test.png' },
     aliyun: { url: '/test.png?image_process=resize,fw_200,fh_200' },
-    awsAmplify: { url: '/?url=%2Ftest.png&w=320&q=100' },
+    awsAmplify: { url: '/?url=%2Ftest.png&w=320&h=200&q=100' },
     cloudflare: { url: '/cdn-cgi/image/w=200,h=200/test.png' },
     cloudinary: { url: '/f_auto,q_auto,w_200,h_200/test' },
     twicpics: { url: '/test.png?twic=v1/cover=200x200' },
@@ -148,7 +148,7 @@ export const images = [
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/fit_contain&s_200x200/test.png' },
     aliyun: { url: '/test.png?image_process=fit,contain/resize,fw_200,fh_200' },
-    awsAmplify: { url: '/?url=%2Ftest.png&w=320&q=100' },
+    awsAmplify: { url: '/?url=%2Ftest.png&w=320&h=200&fit=contain&q=100' },
     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' },
     twicpics: { url: '/test.png?twic=v1/inside=200x200' },
@@ -184,7 +184,7 @@ export const images = [
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/fit_contain&f_jpeg&s_200x200/test.png' },
     aliyun: { url: '/test.png?image_process=fit,contain/format,jpeg/resize,fw_200,fh_200' },
-    awsAmplify: { url: '/?url=%2Ftest.png&w=320&q=100' },
+    awsAmplify: { url: '/?url=%2Ftest.png&w=320&h=200&fit=contain&format=jpeg&q=100' },
     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' },
     twicpics: { url: '/test.png?twic=v1/output=jpeg/inside=200x200' },