Skip to content

Commit 4e952ba

Browse files
khempeniusPawel Kozlowski
authored andcommitted
feat(common): add loaders for cloudinary & imagekit (#47082)
This commit adds loaders for cloudinary and imagekit. PR Close #47082
1 parent 1cf43de commit 4e952ba

File tree

5 files changed

+257
-66
lines changed

5 files changed

+257
-66
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Provider, ɵRuntimeError as RuntimeError} from '@angular/core';
10+
11+
import {RuntimeErrorCode} from '../../../errors';
12+
13+
import {IMAGE_LOADER, ImageLoaderConfig} from './image_loader';
14+
import {isValidPath, normalizePath, normalizeSrc} from './loader_utils';
15+
16+
/**
17+
* Function that generates a built-in ImageLoader for Cloudinary
18+
* and turns it into an Angular provider.
19+
*
20+
* @param path Base URL of your Cloudinary images
21+
* This URL should match one of the following formats:
22+
* https://res.cloudinary.com/mysite
23+
* https://mysite.cloudinary.com
24+
* https://subdomain.mysite.com
25+
* @returns Provider that provides an ImageLoader function
26+
*/
27+
export function provideCloudinaryLoader(path: string): Provider {
28+
if (ngDevMode && !isValidPath(path)) {
29+
throwInvalidPathError(path);
30+
}
31+
path = normalizePath(path);
32+
33+
return {
34+
provide: IMAGE_LOADER,
35+
useValue: (config: ImageLoaderConfig) => {
36+
// Example of a Cloudinary image URL:
37+
// https://res.cloudinary.com/mysite/image/upload/c_scale,f_auto,q_auto,w_600/marketing/tile-topics-m.png
38+
let params = `f_auto,q_auto`; // sets image format and quality to "auto"
39+
if (config.width) {
40+
params += `,w_${config.width}`;
41+
}
42+
const url = `${path}/image/upload/${params}/${normalizeSrc(config.src)}`;
43+
return url;
44+
}
45+
};
46+
}
47+
48+
function throwInvalidPathError(path: unknown): never {
49+
throw new RuntimeError(
50+
RuntimeErrorCode.INVALID_INPUT,
51+
`CloudinaryLoader has detected an invalid path: ` +
52+
`expecting a path matching one of the following formats: https://res.cloudinary.com/mysite, https://mysite.cloudinary.com, or https://subdomain.mysite.com - ` +
53+
`but got: \`${path}\``);
54+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Provider, ɵRuntimeError as RuntimeError} from '@angular/core';
10+
11+
import {RuntimeErrorCode} from '../../../errors';
12+
13+
import {IMAGE_LOADER, ImageLoaderConfig} from './image_loader';
14+
import {isValidPath, normalizePath, normalizeSrc} from './loader_utils';
15+
16+
/**
17+
* Function that generates a built-in ImageLoader for ImageKit
18+
* and turns it into an Angular provider.
19+
*
20+
* @param path Base URL of your ImageKit images
21+
* This URL should match one of the following formats:
22+
* https://ik.imagekit.io/myaccount
23+
* https://subdomain.mysite.com
24+
* @returns Provider that provides an ImageLoader function
25+
*/
26+
export function provideImageKitLoader(path: string): Provider {
27+
if (ngDevMode && !isValidPath(path)) {
28+
throwInvalidPathError(path);
29+
}
30+
path = normalizePath(path);
31+
32+
return {
33+
provide: IMAGE_LOADER,
34+
useValue: (config: ImageLoaderConfig) => {
35+
// Example of an ImageKit image URL:
36+
// https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg
37+
let params = `tr:q-auto`; // applies the "auto quality" transformation
38+
if (config.width) {
39+
params += `,w-${config.width?.toString()}`;
40+
};
41+
const url = `${path}/${params}/${normalizeSrc(config.src)}`;
42+
return url;
43+
}
44+
};
45+
}
46+
47+
function throwInvalidPathError(path: unknown): never {
48+
throw new RuntimeError(
49+
RuntimeErrorCode.INVALID_INPUT,
50+
`ImageKitLoader has detected an invalid path: ` +
51+
`expecting a path matching one of the following formats: https://ik.imagekit.io/mysite or https://subdomain.mysite.com - ` +
52+
`but got: \`${path}\``);
53+
}

packages/common/src/directives/ng_optimized_image/image_loaders/imgix_loader.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {RuntimeErrorCode} from '../../../errors';
1212
import {PRECONNECT_CHECK_BLOCKLIST} from '../preconnect_link_checker';
1313

1414
import {IMAGE_LOADER, ImageLoaderConfig} from './image_loader';
15+
import {isValidPath, normalizePath, normalizeSrc} from './loader_utils';
1516

1617
/**
1718
* Function that generates a built-in ImageLoader for Imgix and turns it
@@ -24,7 +25,9 @@ import {IMAGE_LOADER, ImageLoaderConfig} from './image_loader';
2425
export function provideImgixLoader(path: string, options: {ensurePreconnect?: boolean} = {
2526
ensurePreconnect: true
2627
}) {
27-
ngDevMode && assertValidPath(path);
28+
if (ngDevMode && !isValidPath(path)) {
29+
throwInvalidPathError(path);
30+
}
2831
path = normalizePath(path);
2932

3033
const providers: Provider[] = [{
@@ -45,32 +48,10 @@ export function provideImgixLoader(path: string, options: {ensurePreconnect?: bo
4548
return providers;
4649
}
4750

48-
function assertValidPath(path: unknown) {
49-
const isString = typeof path === 'string';
50-
51-
if (!isString || path.trim() === '') {
52-
throwInvalidPathError(path);
53-
}
54-
55-
try {
56-
const url = new URL(path);
57-
} catch {
58-
throwInvalidPathError(path);
59-
}
60-
}
61-
6251
function throwInvalidPathError(path: unknown): never {
6352
throw new RuntimeError(
6453
RuntimeErrorCode.INVALID_INPUT,
6554
`ImgixLoader has detected an invalid path: ` +
6655
`expecting a path like https://somepath.imgix.net/` +
6756
`but got: \`${path}\``);
6857
}
69-
70-
function normalizePath(path: string) {
71-
return path[path.length - 1] === '/' ? path.slice(0, -1) : path;
72-
}
73-
74-
function normalizeSrc(src: string) {
75-
return src[0] === '/' ? src.slice(1) : src;
76-
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export function isValidPath(path: unknown) {
2+
const isString = typeof path === 'string';
3+
4+
if (!isString || path.trim() === '') {
5+
return false;
6+
}
7+
8+
try {
9+
const url = new URL(path);
10+
return true;
11+
} catch {
12+
return false;
13+
}
14+
}
15+
16+
export function normalizePath(path: string) {
17+
return path.endsWith('/') ? path.slice(0, -1) : path;
18+
}
19+
20+
export function normalizeSrc(src: string) {
21+
return src.startsWith('/') ? src.slice(1) : src;
22+
}

0 commit comments

Comments
 (0)