@angular/common
Version:
Angular - commonly needed directives and services
74 lines • 12.3 kB
JavaScript
/**
* @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 { InjectionToken, ɵRuntimeError as RuntimeError } from '@angular/core';
import { isAbsoluteUrl, isValidPath, normalizePath, normalizeSrc } from '../url';
/**
* Noop image loader that does no transformation to the original src and just returns it as is.
* This loader is used as a default one if more specific logic is not provided in an app config.
*
* @see {@link ImageLoader}
* @see {@link NgOptimizedImage}
*/
export const noopImageLoader = (config) => config.src;
/**
* Injection token that configures the image loader function.
*
* @see {@link ImageLoader}
* @see {@link NgOptimizedImage}
* @publicApi
*/
export const IMAGE_LOADER = new InjectionToken('ImageLoader', {
providedIn: 'root',
factory: () => noopImageLoader,
});
/**
* Internal helper function that makes it easier to introduce custom image loaders for the
* `NgOptimizedImage` directive. It is enough to specify a URL builder function to obtain full DI
* configuration for a given loader: a DI token corresponding to the actual loader function, plus DI
* tokens managing preconnect check functionality.
* @param buildUrlFn a function returning a full URL based on loader's configuration
* @param exampleUrls example of full URLs for a given loader (used in error messages)
* @returns a set of DI providers corresponding to the configured image loader
*/
export function createImageLoader(buildUrlFn, exampleUrls) {
return function provideImageLoader(path) {
if (!isValidPath(path)) {
throwInvalidPathError(path, exampleUrls || []);
}
// The trailing / is stripped (if provided) to make URL construction (concatenation) easier in
// the individual loader functions.
path = normalizePath(path);
const loaderFn = (config) => {
if (isAbsoluteUrl(config.src)) {
// Image loader functions expect an image file name (e.g. `my-image.png`)
// or a relative path + a file name (e.g. `/a/b/c/my-image.png`) as an input,
// so the final absolute URL can be constructed.
// When an absolute URL is provided instead - the loader can not
// build a final URL, thus the error is thrown to indicate that.
throwUnexpectedAbsoluteUrlError(path, config.src);
}
return buildUrlFn(path, { ...config, src: normalizeSrc(config.src) });
};
const providers = [{ provide: IMAGE_LOADER, useValue: loaderFn }];
return providers;
};
}
function throwInvalidPathError(path, exampleUrls) {
throw new RuntimeError(2959 /* RuntimeErrorCode.INVALID_LOADER_ARGUMENTS */, ngDevMode &&
`Image loader has detected an invalid path (\`${path}\`). ` +
`To fix this, supply a path using one of the following formats: ${exampleUrls.join(' or ')}`);
}
function throwUnexpectedAbsoluteUrlError(path, url) {
throw new RuntimeError(2959 /* RuntimeErrorCode.INVALID_LOADER_ARGUMENTS */, ngDevMode &&
`Image loader has detected a \`<img>\` tag with an invalid \`ngSrc\` attribute: ${url}. ` +
`This image loader expects \`ngSrc\` to be a relative URL - ` +
`however the provided value is an absolute URL. ` +
`To fix this, provide \`ngSrc\` as a path relative to the base URL ` +
`configured for this loader (\`${path}\`).`);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2VfbG9hZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3NyYy9kaXJlY3RpdmVzL25nX29wdGltaXplZF9pbWFnZS9pbWFnZV9sb2FkZXJzL2ltYWdlX2xvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsY0FBYyxFQUFZLGFBQWEsSUFBSSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFHdEYsT0FBTyxFQUFDLGFBQWEsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBQyxNQUFNLFFBQVEsQ0FBQztBQWdDL0U7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBQUMsTUFBeUIsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztBQVV6RTs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxjQUFjLENBQWMsYUFBYSxFQUFFO0lBQ3pFLFVBQVUsRUFBRSxNQUFNO0lBQ2xCLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxlQUFlO0NBQy9CLENBQUMsQ0FBQztBQUVIOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUM3QixVQUErRCxFQUFFLFdBQXNCO0lBQ3pGLE9BQU8sU0FBUyxrQkFBa0IsQ0FBQyxJQUFZO1FBQzdDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN2QixxQkFBcUIsQ0FBQyxJQUFJLEVBQUUsV0FBVyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFFRCw4RkFBOEY7UUFDOUYsbUNBQW1DO1FBQ25DLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFM0IsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUF5QixFQUFFLEVBQUU7WUFDN0MsSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzlCLHlFQUF5RTtnQkFDekUsNkVBQTZFO2dCQUM3RSxnREFBZ0Q7Z0JBQ2hELGdFQUFnRTtnQkFDaEUsZ0VBQWdFO2dCQUNoRSwrQkFBK0IsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BELENBQUM7WUFFRCxPQUFPLFVBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBQyxHQUFHLE1BQU0sRUFBRSxHQUFHLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBQyxDQUFDLENBQUM7UUFDdEUsQ0FBQyxDQUFDO1FBRUYsTUFBTSxTQUFTLEdBQWUsQ0FBQyxFQUFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQUM7UUFDNUUsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMscUJBQXFCLENBQUMsSUFBYSxFQUFFLFdBQXFCO0lBQ2pFLE1BQU0sSUFBSSxZQUFZLHVEQUVsQixTQUFTO1FBQ0wsZ0RBQWdELElBQUksT0FBTztZQUN2RCxrRUFDSSxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQsU0FBUywrQkFBK0IsQ0FBQyxJQUFZLEVBQUUsR0FBVztJQUNoRSxNQUFNLElBQUksWUFBWSx1REFFbEIsU0FBUztRQUNMLGtGQUNJLEdBQUcsSUFBSTtZQUNQLDZEQUE2RDtZQUM3RCxpREFBaUQ7WUFDakQsb0VBQW9FO1lBQ3BFLGlDQUFpQyxJQUFJLE1BQU0sQ0FBQyxDQUFDO0FBQzNELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtJbmplY3Rpb25Ub2tlbiwgUHJvdmlkZXIsIMm1UnVudGltZUVycm9yIGFzIFJ1bnRpbWVFcnJvcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7UnVudGltZUVycm9yQ29kZX0gZnJvbSAnLi4vLi4vLi4vZXJyb3JzJztcbmltcG9ydCB7aXNBYnNvbHV0ZVVybCwgaXNWYWxpZFBhdGgsIG5vcm1hbGl6ZVBhdGgsIG5vcm1hbGl6ZVNyY30gZnJvbSAnLi4vdXJsJztcblxuLyoqXG4gKiBDb25maWcgb3B0aW9ucyByZWNvZ25pemVkIGJ5IHRoZSBpbWFnZSBsb2FkZXIgZnVuY3Rpb24uXG4gKlxuICogQHNlZSB7QGxpbmsgSW1hZ2VMb2FkZXJ9XG4gKiBAc2VlIHtAbGluayBOZ09wdGltaXplZEltYWdlfVxuICogQHB1YmxpY0FwaVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEltYWdlTG9hZGVyQ29uZmlnIHtcbiAgLyoqXG4gICAqIEltYWdlIGZpbGUgbmFtZSB0byBiZSBhZGRlZCB0byB0aGUgaW1hZ2UgcmVxdWVzdCBVUkwuXG4gICAqL1xuICBzcmM6IHN0cmluZztcbiAgLyoqXG4gICAqIFdpZHRoIG9mIHRoZSByZXF1ZXN0ZWQgaW1hZ2UgKHRvIGJlIHVzZWQgd2hlbiBnZW5lcmF0aW5nIHNyY3NldCkuXG4gICAqL1xuICB3aWR0aD86IG51bWJlcjtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgdXNlci1wcm92aWRlZCBwYXJhbWV0ZXJzIGZvciB1c2UgYnkgdGhlIEltYWdlTG9hZGVyLlxuICAgKi9cbiAgbG9hZGVyUGFyYW1zPzoge1trZXk6IHN0cmluZ106IGFueTt9O1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYW4gaW1hZ2UgbG9hZGVyIGZ1bmN0aW9uLiBJbWFnZSBsb2FkZXIgZnVuY3Rpb25zIGFyZSB1c2VkIGJ5IHRoZVxuICogTmdPcHRpbWl6ZWRJbWFnZSBkaXJlY3RpdmUgdG8gcHJvZHVjZSBmdWxsIGltYWdlIFVSTCBiYXNlZCBvbiB0aGUgaW1hZ2UgbmFtZSBhbmQgaXRzIHdpZHRoLlxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IHR5cGUgSW1hZ2VMb2FkZXIgPSAoY29uZmlnOiBJbWFnZUxvYWRlckNvbmZpZykgPT4gc3RyaW5nO1xuXG4vKipcbiAqIE5vb3AgaW1hZ2UgbG9hZGVyIHRoYXQgZG9lcyBubyB0cmFuc2Zvcm1hdGlvbiB0byB0aGUgb3JpZ2luYWwgc3JjIGFuZCBqdXN0IHJldHVybnMgaXQgYXMgaXMuXG4gKiBUaGlzIGxvYWRlciBpcyB1c2VkIGFzIGEgZGVmYXVsdCBvbmUgaWYgbW9yZSBzcGVjaWZpYyBsb2dpYyBpcyBub3QgcHJvdmlkZWQgaW4gYW4gYXBwIGNvbmZpZy5cbiAqXG4gKiBAc2VlIHtAbGluayBJbWFnZUxvYWRlcn1cbiAqIEBzZWUge0BsaW5rIE5nT3B0aW1pemVkSW1hZ2V9XG4gKi9cbmV4cG9ydCBjb25zdCBub29wSW1hZ2VMb2FkZXIgPSAoY29uZmlnOiBJbWFnZUxvYWRlckNvbmZpZykgPT4gY29uZmlnLnNyYztcblxuLyoqXG4gKiBNZXRhZGF0YSBhYm91dCB0aGUgaW1hZ2UgbG9hZGVyLlxuICovXG5leHBvcnQgdHlwZSBJbWFnZUxvYWRlckluZm8gPSB7XG4gIG5hbWU6IHN0cmluZyxcbiAgdGVzdFVybDogKHVybDogc3RyaW5nKSA9PiBib29sZWFuXG59O1xuXG4vKipcbiAqIEluamVjdGlvbiB0b2tlbiB0aGF0IGNvbmZpZ3VyZXMgdGhlIGltYWdlIGxvYWRlciBmdW5jdGlvbi5cbiAqXG4gKiBAc2VlIHtAbGluayBJbWFnZUxvYWRlcn1cbiAqIEBzZWUge0BsaW5rIE5nT3B0aW1pemVkSW1hZ2V9XG4gKiBAcHVibGljQXBpXG4gKi9cbmV4cG9ydCBjb25zdCBJTUFHRV9MT0FERVIgPSBuZXcgSW5qZWN0aW9uVG9rZW48SW1hZ2VMb2FkZXI+KCdJbWFnZUxvYWRlcicsIHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxuICBmYWN0b3J5OiAoKSA9PiBub29wSW1hZ2VMb2FkZXIsXG59KTtcblxuLyoqXG4gKiBJbnRlcm5hbCBoZWxwZXIgZnVuY3Rpb24gdGhhdCBtYWtlcyBpdCBlYXNpZXIgdG8gaW50cm9kdWNlIGN1c3RvbSBpbWFnZSBsb2FkZXJzIGZvciB0aGVcbiAqIGBOZ09wdGltaXplZEltYWdlYCBkaXJlY3RpdmUuIEl0IGlzIGVub3VnaCB0byBzcGVjaWZ5IGEgVVJMIGJ1aWxkZXIgZnVuY3Rpb24gdG8gb2J0YWluIGZ1bGwgRElcbiAqIGNvbmZpZ3VyYXRpb24gZm9yIGEgZ2l2ZW4gbG9hZGVyOiBhIERJIHRva2VuIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGFjdHVhbCBsb2FkZXIgZnVuY3Rpb24sIHBsdXMgRElcbiAqIHRva2VucyBtYW5hZ2luZyBwcmVjb25uZWN0IGNoZWNrIGZ1bmN0aW9uYWxpdHkuXG4gKiBAcGFyYW0gYnVpbGRVcmxGbiBhIGZ1bmN0aW9uIHJldHVybmluZyBhIGZ1bGwgVVJMIGJhc2VkIG9uIGxvYWRlcidzIGNvbmZpZ3VyYXRpb25cbiAqIEBwYXJhbSBleGFtcGxlVXJscyBleGFtcGxlIG9mIGZ1bGwgVVJMcyBmb3IgYSBnaXZlbiBsb2FkZXIgKHVzZWQgaW4gZXJyb3IgbWVzc2FnZXMpXG4gKiBAcmV0dXJucyBhIHNldCBvZiBESSBwcm92aWRlcnMgY29ycmVzcG9uZGluZyB0byB0aGUgY29uZmlndXJlZCBpbWFnZSBsb2FkZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUltYWdlTG9hZGVyKFxuICAgIGJ1aWxkVXJsRm46IChwYXRoOiBzdHJpbmcsIGNvbmZpZzogSW1hZ2VMb2FkZXJDb25maWcpID0+IHN0cmluZywgZXhhbXBsZVVybHM/OiBzdHJpbmdbXSkge1xuICByZXR1cm4gZnVuY3Rpb24gcHJvdmlkZUltYWdlTG9hZGVyKHBhdGg6IHN0cmluZykge1xuICAgIGlmICghaXNWYWxpZFBhdGgocGF0aCkpIHtcbiAgICAgIHRocm93SW52YWxpZFBhdGhFcnJvcihwYXRoLCBleGFtcGxlVXJscyB8fCBbXSk7XG4gICAgfVxuXG4gICAgLy8gVGhlIHRyYWlsaW5nIC8gaXMgc3RyaXBwZWQgKGlmIHByb3ZpZGVkKSB0byBtYWtlIFVSTCBjb25zdHJ1Y3Rpb24gKGNvbmNhdGVuYXRpb24pIGVhc2llciBpblxuICAgIC8vIHRoZSBpbmRpdmlkdWFsIGxvYWRlciBmdW5jdGlvbnMuXG4gICAgcGF0aCA9IG5vcm1hbGl6ZVBhdGgocGF0aCk7XG5cbiAgICBjb25zdCBsb2FkZXJGbiA9IChjb25maWc6IEltYWdlTG9hZGVyQ29uZmlnKSA9PiB7XG4gICAgICBpZiAoaXNBYnNvbHV0ZVVybChjb25maWcuc3JjKSkge1xuICAgICAgICAvLyBJbWFnZSBsb2FkZXIgZnVuY3Rpb25zIGV4cGVjdCBhbiBpbWFnZSBmaWxlIG5hbWUgKGUuZy4gYG15LWltYWdlLnBuZ2ApXG4gICAgICAgIC8vIG9yIGEgcmVsYXRpdmUgcGF0aCArIGEgZmlsZSBuYW1lIChlLmcuIGAvYS9iL2MvbXktaW1hZ2UucG5nYCkgYXMgYW4gaW5wdXQsXG4gICAgICAgIC8vIHNvIHRoZSBmaW5hbCBhYnNvbHV0ZSBVUkwgY2FuIGJlIGNvbnN0cnVjdGVkLlxuICAgICAgICAvLyBXaGVuIGFuIGFic29sdXRlIFVSTCBpcyBwcm92aWRlZCBpbnN0ZWFkIC0gdGhlIGxvYWRlciBjYW4gbm90XG4gICAgICAgIC8vIGJ1aWxkIGEgZmluYWwgVVJMLCB0aHVzIHRoZSBlcnJvciBpcyB0aHJvd24gdG8gaW5kaWNhdGUgdGhhdC5cbiAgICAgICAgdGhyb3dVbmV4cGVjdGVkQWJzb2x1dGVVcmxFcnJvcihwYXRoLCBjb25maWcuc3JjKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGJ1aWxkVXJsRm4ocGF0aCwgey4uLmNvbmZpZywgc3JjOiBub3JtYWxpemVTcmMoY29uZmlnLnNyYyl9KTtcbiAgICB9O1xuXG4gICAgY29uc3QgcHJvdmlkZXJzOiBQcm92aWRlcltdID0gW3twcm92aWRlOiBJTUFHRV9MT0FERVIsIHVzZVZhbHVlOiBsb2FkZXJGbn1dO1xuICAgIHJldHVybiBwcm92aWRlcnM7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHRocm93SW52YWxpZFBhdGhFcnJvcihwYXRoOiB1bmtub3duLCBleGFtcGxlVXJsczogc3RyaW5nW10pOiBuZXZlciB7XG4gIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgICBSdW50aW1lRXJyb3JDb2RlLklOVkFMSURfTE9BREVSX0FSR1VNRU5UUyxcbiAgICAgIG5nRGV2TW9kZSAmJlxuICAgICAgICAgIGBJbWFnZSBsb2FkZXIgaGFzIGRldGVjdGVkIGFuIGludmFsaWQgcGF0aCAoXFxgJHtwYXRofVxcYCkuIGAgK1xuICAgICAgICAgICAgICBgVG8gZml4IHRoaXMsIHN1cHBseSBhIHBhdGggdXNpbmcgb25lIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0czogJHtcbiAgICAgICAgICAgICAgICAgIGV4YW1wbGVVcmxzLmpvaW4oJyBvciAnKX1gKTtcbn1cblxuZnVuY3Rpb24gdGhyb3dVbmV4cGVjdGVkQWJzb2x1dGVVcmxFcnJvcihwYXRoOiBzdHJpbmcsIHVybDogc3RyaW5nKTogbmV2ZXIge1xuICB0aHJvdyBuZXcgUnVudGltZUVycm9yKFxuICAgICAgUnVudGltZUVycm9yQ29kZS5JTlZBTElEX0xPQURFUl9BUkdVTUVOVFMsXG4gICAgICBuZ0Rldk1vZGUgJiZcbiAgICAgICAgICBgSW1hZ2UgbG9hZGVyIGhhcyBkZXRlY3RlZCBhIFxcYDxpbWc+XFxgIHRhZyB3aXRoIGFuIGludmFsaWQgXFxgbmdTcmNcXGAgYXR0cmlidXRlOiAke1xuICAgICAgICAgICAgICB1cmx9LiBgICtcbiAgICAgICAgICAgICAgYFRoaXMgaW1hZ2UgbG9hZGVyIGV4cGVjdHMgXFxgbmdTcmNcXGAgdG8gYmUgYSByZWxhdGl2ZSBVUkwgLSBgICtcbiAgICAgICAgICAgICAgYGhvd2V2ZXIgdGhlIHByb3ZpZGVkIHZhbHVlIGlzIGFuIGFic29sdXRlIFVSTC4gYCArXG4gICAgICAgICAgICAgIGBUbyBmaXggdGhpcywgcHJvdmlkZSBcXGBuZ1NyY1xcYCBhcyBhIHBhdGggcmVsYXRpdmUgdG8gdGhlIGJhc2UgVVJMIGAgK1xuICAgICAgICAgICAgICBgY29uZmlndXJlZCBmb3IgdGhpcyBsb2FkZXIgKFxcYCR7cGF0aH1cXGApLmApO1xufVxuIl19