Repository: nuxt/image
Pull request #1361 (2024-05-10 17:38:39)

feat(cloudinary): support reading project from absolute url
Resolves https://github.com/nuxt/image/issues/1376

Adds the ability for a full cloudinary url to be used as `src` instead of relying on `baseURL` to construct the image url.

For example:
```vue
<NuxtImg src="https://res.cloudinary.com/example/image/upload/example.jpg" />
```
should use `https://res.cloudinary.com/example/image/upload` as the `baseURL`, regardless of what `baseURL` is configured as.

This is needed for apps that receive a full cloudinary url from the backend which may be responsible for determining the specific cloud and base url.

See discussion in Discord thread: https://discord.com/channels/473401852243869706/1238298456540577802

danielroe: Would you be able to add an example to the test suite? 🙏 
markbrouch: @danielroe - I have added an example to the test suite in https://github.com/nuxt/image/pull/1361/commits/cc869978c6523a73333c42f1904982a1833e5ab6
codecov-commenter: ## [Codecov](https://app.codecov.io/gh/nuxt/image/pull/1361?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 62.31%. Comparing base [(`2b6a877`)](https://app.codecov.io/gh/nuxt/image/commit/2b6a877a9d61923d22602707a5568a3c0deb6818?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt) to head [(`cc86997`)](https://app.codecov.io/gh/nuxt/image/commit/cc869978c6523a73333c42f1904982a1833e5ab6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1361      +/-   ##
==========================================
+ Coverage   62.26%   62.31%   +0.05%     
==========================================
  Files          79       79              
  Lines        3599     3604       +5     
  Branches      398      399       +1     
==========================================
+ Hits         2241     2246       +5     
  Misses       1328     1328              
  Partials       30       30              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/nuxt/image/pull/1361?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt).


Patch:
diff --git a/src/runtime/providers/cloudinary.ts b/src/runtime/providers/cloudinary.ts
index 74f7916..4cd41c6 100644
--- a/src/runtime/providers/cloudinary.ts
+++ b/src/runtime/providers/cloudinary.ts
@@ -82,11 +82,20 @@ const defaultModifiers = {
   quality: 'auto',
 }
 
+const REMOTE_MAPPING_RE = /\/image\/upload\/(.*)$/
+
 export const getImage: ProviderGetImage = (src, { modifiers = {}, baseURL = '/' } = {}) => {
   const mergeModifiers = defu(modifiers, defaultModifiers)
   const operations = operationsGenerator(mergeModifiers as any)
 
-  const remoteFolderMapping = baseURL.match(/\/image\/upload\/(.*)/)
+  // Check if the src is a Cloudinary URL
+  const srcMapping = src.match(REMOTE_MAPPING_RE)?.[1]
+  if (srcMapping) {
+    baseURL = src.replace(srcMapping, '')
+    src = srcMapping
+  }
+
+  const remoteFolderMapping = baseURL.match(REMOTE_MAPPING_RE)
   // Handle delivery remote media file URLs
   // see: https://cloudinary.com/documentation/fetch_remote_images
   // Note: Non-remote images will pass into this function if the baseURL is not using a sub directory


Test patch:
diff --git a/test/unit/providers.test.ts b/test/unit/providers.test.ts
index 7869e54..28fae69 100644
--- a/test/unit/providers.test.ts
+++ b/test/unit/providers.test.ts
@@ -117,6 +117,14 @@ describe('Providers', () => {
     }
   })
 
+  it('cloudinary absolute url', () => {
+    const absoluteUrl = 'https://res.cloudinary.com/example/image/upload/test.png'
+    const generated = cloudinary.getImage(absoluteUrl, { modifiers: { width: 300, height: 300 } }, emptyContext)
+    expect(generated).toMatchObject({
+      url: 'https://res.cloudinary.com/example/image/upload/f_auto,q_auto,w_300,h_300/test.png',
+    })
+  })
+
   it('cloudinary fetch', () => {
     const providerOptions = {
       baseURL: 'https://res.cloudinary.com/demo/image/fetch/',