Skip to content

Commit

Permalink
feat(common): add loaders for cloudinary & imagekit (#47082)
Browse files Browse the repository at this point in the history
This commit adds loaders for cloudinary and imagekit.

PR Close #47082
  • Loading branch information
khempenius authored and Pawel Kozlowski committed Aug 16, 2022
1 parent 1cf43de commit 4e952ba
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 66 deletions.
@@ -0,0 +1,54 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Provider, ɵRuntimeError as RuntimeError} from '@angular/core';

import {RuntimeErrorCode} from '../../../errors';

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

/**
* Function that generates a built-in ImageLoader for Cloudinary
* and turns it into an Angular provider.
*
* @param path Base URL of your Cloudinary images
* This URL should match one of the following formats:
* https://res.cloudinary.com/mysite
* https://mysite.cloudinary.com
* https://subdomain.mysite.com
* @returns Provider that provides an ImageLoader function
*/
export function provideCloudinaryLoader(path: string): Provider {
if (ngDevMode && !isValidPath(path)) {
throwInvalidPathError(path);
}
path = normalizePath(path);

return {
provide: IMAGE_LOADER,
useValue: (config: ImageLoaderConfig) => {
// Example of a Cloudinary image URL:
// https://res.cloudinary.com/mysite/image/upload/c_scale,f_auto,q_auto,w_600/marketing/tile-topics-m.png
let params = `f_auto,q_auto`; // sets image format and quality to "auto"
if (config.width) {
params += `,w_${config.width}`;
}
const url = `${path}/image/upload/${params}/${normalizeSrc(config.src)}`;
return url;
}
};
}

function throwInvalidPathError(path: unknown): never {
throw new RuntimeError(
RuntimeErrorCode.INVALID_INPUT,
`CloudinaryLoader has detected an invalid path: ` +
`expecting a path matching one of the following formats: https://res.cloudinary.com/mysite, https://mysite.cloudinary.com, or https://subdomain.mysite.com - ` +
`but got: \`${path}\``);
}
@@ -0,0 +1,53 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Provider, ɵRuntimeError as RuntimeError} from '@angular/core';

import {RuntimeErrorCode} from '../../../errors';

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

/**
* Function that generates a built-in ImageLoader for ImageKit
* and turns it into an Angular provider.
*
* @param path Base URL of your ImageKit images
* This URL should match one of the following formats:
* https://ik.imagekit.io/myaccount
* https://subdomain.mysite.com
* @returns Provider that provides an ImageLoader function
*/
export function provideImageKitLoader(path: string): Provider {
if (ngDevMode && !isValidPath(path)) {
throwInvalidPathError(path);
}
path = normalizePath(path);

return {
provide: IMAGE_LOADER,
useValue: (config: ImageLoaderConfig) => {
// Example of an ImageKit image URL:
// https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg
let params = `tr:q-auto`; // applies the "auto quality" transformation
if (config.width) {
params += `,w-${config.width?.toString()}`;
};
const url = `${path}/${params}/${normalizeSrc(config.src)}`;
return url;
}
};
}

function throwInvalidPathError(path: unknown): never {
throw new RuntimeError(
RuntimeErrorCode.INVALID_INPUT,
`ImageKitLoader has detected an invalid path: ` +
`expecting a path matching one of the following formats: https://ik.imagekit.io/mysite or https://subdomain.mysite.com - ` +
`but got: \`${path}\``);
}
Expand Up @@ -12,6 +12,7 @@ import {RuntimeErrorCode} from '../../../errors';
import {PRECONNECT_CHECK_BLOCKLIST} from '../preconnect_link_checker';

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

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

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

function assertValidPath(path: unknown) {
const isString = typeof path === 'string';

if (!isString || path.trim() === '') {
throwInvalidPathError(path);
}

try {
const url = new URL(path);
} catch {
throwInvalidPathError(path);
}
}

function throwInvalidPathError(path: unknown): never {
throw new RuntimeError(
RuntimeErrorCode.INVALID_INPUT,
`ImgixLoader has detected an invalid path: ` +
`expecting a path like https://somepath.imgix.net/` +
`but got: \`${path}\``);
}

function normalizePath(path: string) {
return path[path.length - 1] === '/' ? path.slice(0, -1) : path;
}

function normalizeSrc(src: string) {
return src[0] === '/' ? src.slice(1) : src;
}
@@ -0,0 +1,22 @@
export function isValidPath(path: unknown) {
const isString = typeof path === 'string';

if (!isString || path.trim() === '') {
return false;
}

try {
const url = new URL(path);
return true;
} catch {
return false;
}
}

export function normalizePath(path: string) {
return path.endsWith('/') ? path.slice(0, -1) : path;
}

export function normalizeSrc(src: string) {
return src.startsWith('/') ? src.slice(1) : src;
}

0 comments on commit 4e952ba

Please sign in to comment.