Skip to content

Commit

Permalink
Merge pull request #614 from simonihmig/cloudinary-transformations
Browse files Browse the repository at this point in the history
Use Record-based API for Cloudinary transformations
  • Loading branch information
simonihmig authored Jun 9, 2024
2 parents 8f76593 + ca743af commit b790caa
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 20 deletions.
33 changes: 33 additions & 0 deletions .changeset/mean-pots-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
'@responsive-image/cdn': major
'@responsive-image/ember': major
---

Use Record-based API for cloudinary transformations

Instead of passing cloudinary transformations as a string according to the Cloudinary Transformation URL API, you need to pass them as an object. If you want to use chained transformations, pass an array of objects.

```js
// using @resposive-image/cdn
const simpleTransformation = cloudinaryProvider('foo/bar.jpg', {
transformations: { co: 'rgb:20a020', e: 'colorize:50' },
});

const chainedTransformation = cloudinaryProvider('foo/bar.jpg', {
transformations: [
{ co: 'rgb:20a020', e: 'colorize:50' },
{ ar: '1.0', c: 'fill', w: '150' },
{ r: 'max' },
],
});
```

```hbs
{{!-- using @responsive-image/ember }}
<ResponsiveImage
@src={{responsiveImageCloudinaryProvider
"foo/bar.jpg"
transformations=(hash co="rgb:20a020" e="colorize:50")
}}
>
```
4 changes: 3 additions & 1 deletion docs/cdn/cloudinary.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ you can add your own [Cloudinary transformations](https://cloudinary.com/documen
<ResponsiveImage
@src={{responsive-image-cloudinary-provider
'path/to/uploaded/image.jpg'
transformations='e_sharpen:400,e_grayscale'
transformations=(hash co='rgb:20a020' e='colorize:50')
}}
/>
```

It accepts an object of transformations, or an array of objects for [chained transformations](https://cloudinary.com/documentation/image_transformations#chained_transformations).

### Quality

Use the `quality` parameter to pass a custom [quality](https://cloudinary.com/documentation/transformation_reference#q_quality) setting
Expand Down
30 changes: 24 additions & 6 deletions packages/cdn/src/cloudinary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ export interface CloudinaryConfig {
cloudName: string;
}

type CloudinaryTransformation = Record<string, string | number>;

export interface CloudinaryOptions {
transformations?: string;
transformations?: CloudinaryTransformation | CloudinaryTransformation[];
formats?: ImageType[];
quality?: number;
}
Expand Down Expand Up @@ -46,14 +48,30 @@ export function cloudinaryProvider(
return {
imageTypes: options.formats ?? ['png', 'jpeg', 'webp', 'avif'],
imageUrlFor(width: number, type: ImageType = 'jpeg'): string {
let resizeParams = `w_${width},c_limit,q_${options.quality ?? 'auto'}`;
const resizeParams: CloudinaryTransformation = {
w: width,
c: 'limit',
q: options.quality ?? 'auto',
};
if (deliveryType !== 'upload') {
resizeParams += `,f_${formatMap[type] ?? type}`;
resizeParams['f'] = formatMap[type] ?? type;
}

const params = options.transformations
? `${options.transformations}/${resizeParams}`
: resizeParams;
const transformations = options.transformations
? Array.isArray(options.transformations)
? options.transformations
: [options.transformations]
: [];

transformations.push(resizeParams);

const params = transformations
.map((transformation) =>
Object.entries(transformation)
.map(([key, value]) => `${key}_${value}`)
.join(','),
)
.join('/');

return `https://res.cloudinary.com/${cloudName}/image/${deliveryType}/${params}/${imageId}${
deliveryType === 'upload' ? '.' + type : ''
Expand Down
8 changes: 6 additions & 2 deletions packages/cdn/tests/cloudinary.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('cloudinary', function () {

test('it returns custom params', function () {
const result = cloudinaryProvider('foo/bar.jpg', {
transformations: 'co_rgb:20a020,e_colorize:50',
transformations: { co: 'rgb:20a020', e: 'colorize:50' },
});

expect(result.imageUrlFor(100, 'jpeg')).toBe(
Expand All @@ -55,7 +55,11 @@ describe('cloudinary', function () {

test('it returns custom chained params', function () {
const result = cloudinaryProvider('foo/bar.jpg', {
transformations: 'co_rgb:20a020,e_colorize:50/ar_1.0,c_fill,w_150/r_max',
transformations: [
{ co: 'rgb:20a020', e: 'colorize:50' },
{ ar: '1.0', c: 'fill', w: '150' },
{ r: 'max' },
],
});

expect(result.imageUrlFor(100, 'jpeg')).toBe(
Expand Down
16 changes: 8 additions & 8 deletions test-app/app/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@

<ResponsiveImage
@src={{responsive-image-cloudinary-provider
'https://upload.wikimedia.org/wikipedia/commons/1/13/Benedict_Cumberbatch_2011.png'
transformations='e_grayscale'
"https://upload.wikimedia.org/wikipedia/commons/1/13/Benedict_Cumberbatch_2011.png"
transformations=(hash e="grayscale")
}}
/>
<ResponsiveImage
@src={{responsive-image-cloudinary-provider
'samples/animals/three-dogs'
transformations='e_grayscale'
"samples/animals/three-dogs"
transformations=(hash e="grayscale")
}}
/>

<ResponsiveImage
@src={{responsive-image-cloudinary-provider
'samples/animals/three-dogs'
formats=(array 'webp' 'avif')
"samples/animals/three-dogs"
formats=(array "webp" "avif")
}}
@width={{160}}
/>
Expand All @@ -27,8 +27,8 @@

<ResponsiveImage
@src={{responsive-image-imgix-provider
'pages/approach/agile_2000x1200.jpg'
params=(hash monochrome='44768B')
"pages/approach/agile_2000x1200.jpg"
params=(hash monochrome="44768B")
}}
@width={{320}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "ember-qunit";
import { render, type RenderingTestContext } from "@ember/test-helpers";
import { array } from "@ember/helper";
import { array, hash } from "@ember/helper";
import responsiveImageCloudinaryProvider from "@responsive-image/ember/helpers/responsive-image-cloudinary-provider";
import type { ImageData } from "@responsive-image/ember";

Expand Down Expand Up @@ -89,7 +89,7 @@ module(
{{dump
(responsiveImageCloudinaryProvider
"samples/animals/three-dogs"
transformations="co_rgb:20a020,e_colorize:50"
transformations=(hash co="rgb:20a020" e="colorize:50")
)
}}
</template>,
Expand All @@ -107,7 +107,11 @@ module(
{{dump
(responsiveImageCloudinaryProvider
"samples/animals/three-dogs"
transformations="co_rgb:20a020,e_colorize:50/ar_1.0,c_fill,w_150/r_max"
transformations=(array
(hash co="rgb:20a020" e="colorize:50")
(hash ar="1.0" c="fill" w="150")
(hash r="max")
)
)
}}
</template>,
Expand Down

0 comments on commit b790caa

Please sign in to comment.