@angular/common
Version:
Angular - commonly needed directives and services
74 lines • 12.5 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(ngDevMode ? '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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2VfbG9hZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3NyYy9kaXJlY3RpdmVzL25nX29wdGltaXplZF9pbWFnZS9pbWFnZV9sb2FkZXJzL2ltYWdlX2xvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsY0FBYyxFQUFZLGFBQWEsSUFBSSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFHdEYsT0FBTyxFQUFDLGFBQWEsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBQyxNQUFNLFFBQVEsQ0FBQztBQXFDL0U7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBQUMsTUFBeUIsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztBQVV6RTs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxjQUFjLENBQWMsU0FBUyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtJQUMxRixVQUFVLEVBQUUsTUFBTTtJQUNsQixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsZUFBZTtDQUMvQixDQUFDLENBQUM7QUFFSDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDL0IsVUFBK0QsRUFDL0QsV0FBc0I7SUFFdEIsT0FBTyxTQUFTLGtCQUFrQixDQUFDLElBQVk7UUFDN0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLHFCQUFxQixDQUFDLElBQUksRUFBRSxXQUFXLElBQUksRUFBRSxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUVELDhGQUE4RjtRQUM5RixtQ0FBbUM7UUFDbkMsSUFBSSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUzQixNQUFNLFFBQVEsR0FBRyxDQUFDLE1BQXlCLEVBQUUsRUFBRTtZQUM3QyxJQUFJLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDOUIseUVBQXlFO2dCQUN6RSw2RUFBNkU7Z0JBQzdFLGdEQUFnRDtnQkFDaEQsZ0VBQWdFO2dCQUNoRSxnRUFBZ0U7Z0JBQ2hFLCtCQUErQixDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDcEQsQ0FBQztZQUVELE9BQU8sVUFBVSxDQUFDLElBQUksRUFBRSxFQUFDLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUN0RSxDQUFDLENBQUM7UUFFRixNQUFNLFNBQVMsR0FBZSxDQUFDLEVBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQztRQUM1RSxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxxQkFBcUIsQ0FBQyxJQUFhLEVBQUUsV0FBcUI7SUFDakUsTUFBTSxJQUFJLFlBQVksdURBRXBCLFNBQVM7UUFDUCxnREFBZ0QsSUFBSSxPQUFPO1lBQ3pELGtFQUFrRSxXQUFXLENBQUMsSUFBSSxDQUNoRixNQUFNLENBQ1AsRUFBRSxDQUNSLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUywrQkFBK0IsQ0FBQyxJQUFZLEVBQUUsR0FBVztJQUNoRSxNQUFNLElBQUksWUFBWSx1REFFcEIsU0FBUztRQUNQLGtGQUFrRixHQUFHLElBQUk7WUFDdkYsNkRBQTZEO1lBQzdELGlEQUFpRDtZQUNqRCxvRUFBb0U7WUFDcEUsaUNBQWlDLElBQUksTUFBTSxDQUNoRCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0luamVjdGlvblRva2VuLCBQcm92aWRlciwgybVSdW50aW1lRXJyb3IgYXMgUnVudGltZUVycm9yfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtSdW50aW1lRXJyb3JDb2RlfSBmcm9tICcuLi8uLi8uLi9lcnJvcnMnO1xuaW1wb3J0IHtpc0Fic29sdXRlVXJsLCBpc1ZhbGlkUGF0aCwgbm9ybWFsaXplUGF0aCwgbm9ybWFsaXplU3JjfSBmcm9tICcuLi91cmwnO1xuXG4vKipcbiAqIENvbmZpZyBvcHRpb25zIHJlY29nbml6ZWQgYnkgdGhlIGltYWdlIGxvYWRlciBmdW5jdGlvbi5cbiAqXG4gKiBAc2VlIHtAbGluayBJbWFnZUxvYWRlcn1cbiAqIEBzZWUge0BsaW5rIE5nT3B0aW1pemVkSW1hZ2V9XG4gKiBAcHVibGljQXBpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW1hZ2VMb2FkZXJDb25maWcge1xuICAvKipcbiAgICogSW1hZ2UgZmlsZSBuYW1lIHRvIGJlIGFkZGVkIHRvIHRoZSBpbWFnZSByZXF1ZXN0IFVSTC5cbiAgICovXG4gIHNyYzogc3RyaW5nO1xuICAvKipcbiAgICogV2lkdGggb2YgdGhlIHJlcXVlc3RlZCBpbWFnZSAodG8gYmUgdXNlZCB3aGVuIGdlbmVyYXRpbmcgc3Jjc2V0KS5cbiAgICovXG4gIHdpZHRoPzogbnVtYmVyO1xuICAvKipcbiAgICogV2hldGhlciB0aGUgbG9hZGVyIHNob3VsZCBnZW5lcmF0ZSBhIFVSTCBmb3IgYSBzbWFsbCBpbWFnZSBwbGFjZWhvbGRlciBpbnN0ZWFkIG9mIGEgZnVsbC1zaXplZFxuICAgKiBpbWFnZS5cbiAgICovXG4gIGlzUGxhY2Vob2xkZXI/OiBib29sZWFuO1xuICAvKipcbiAgICogQWRkaXRpb25hbCB1c2VyLXByb3ZpZGVkIHBhcmFtZXRlcnMgZm9yIHVzZSBieSB0aGUgSW1hZ2VMb2FkZXIuXG4gICAqL1xuICBsb2FkZXJQYXJhbXM/OiB7W2tleTogc3RyaW5nXTogYW55fTtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGFuIGltYWdlIGxvYWRlciBmdW5jdGlvbi4gSW1hZ2UgbG9hZGVyIGZ1bmN0aW9ucyBhcmUgdXNlZCBieSB0aGVcbiAqIE5nT3B0aW1pemVkSW1hZ2UgZGlyZWN0aXZlIHRvIHByb2R1Y2UgZnVsbCBpbWFnZSBVUkwgYmFzZWQgb24gdGhlIGltYWdlIG5hbWUgYW5kIGl0cyB3aWR0aC5cbiAqXG4gKiBAcHVibGljQXBpXG4gKi9cbmV4cG9ydCB0eXBlIEltYWdlTG9hZGVyID0gKGNvbmZpZzogSW1hZ2VMb2FkZXJDb25maWcpID0+IHN0cmluZztcblxuLyoqXG4gKiBOb29wIGltYWdlIGxvYWRlciB0aGF0IGRvZXMgbm8gdHJhbnNmb3JtYXRpb24gdG8gdGhlIG9yaWdpbmFsIHNyYyBhbmQganVzdCByZXR1cm5zIGl0IGFzIGlzLlxuICogVGhpcyBsb2FkZXIgaXMgdXNlZCBhcyBhIGRlZmF1bHQgb25lIGlmIG1vcmUgc3BlY2lmaWMgbG9naWMgaXMgbm90IHByb3ZpZGVkIGluIGFuIGFwcCBjb25maWcuXG4gKlxuICogQHNlZSB7QGxpbmsgSW1hZ2VMb2FkZXJ9XG4gKiBAc2VlIHtAbGluayBOZ09wdGltaXplZEltYWdlfVxuICovXG5leHBvcnQgY29uc3Qgbm9vcEltYWdlTG9hZGVyID0gKGNvbmZpZzogSW1hZ2VMb2FkZXJDb25maWcpID0+IGNvbmZpZy5zcmM7XG5cbi8qKlxuICogTWV0YWRhdGEgYWJvdXQgdGhlIGltYWdlIGxvYWRlci5cbiAqL1xuZXhwb3J0IHR5cGUgSW1hZ2VMb2FkZXJJbmZvID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIHRlc3RVcmw6ICh1cmw6IHN0cmluZykgPT4gYm9vbGVhbjtcbn07XG5cbi8qKlxuICogSW5qZWN0aW9uIHRva2VuIHRoYXQgY29uZmlndXJlcyB0aGUgaW1hZ2UgbG9hZGVyIGZ1bmN0aW9uLlxuICpcbiAqIEBzZWUge0BsaW5rIEltYWdlTG9hZGVyfVxuICogQHNlZSB7QGxpbmsgTmdPcHRpbWl6ZWRJbWFnZX1cbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGNvbnN0IElNQUdFX0xPQURFUiA9IG5ldyBJbmplY3Rpb25Ub2tlbjxJbWFnZUxvYWRlcj4obmdEZXZNb2RlID8gJ0ltYWdlTG9hZGVyJyA6ICcnLCB7XG4gIHByb3ZpZGVkSW46ICdyb290JyxcbiAgZmFjdG9yeTogKCkgPT4gbm9vcEltYWdlTG9hZGVyLFxufSk7XG5cbi8qKlxuICogSW50ZXJuYWwgaGVscGVyIGZ1bmN0aW9uIHRoYXQgbWFrZXMgaXQgZWFzaWVyIHRvIGludHJvZHVjZSBjdXN0b20gaW1hZ2UgbG9hZGVycyBmb3IgdGhlXG4gKiBgTmdPcHRpbWl6ZWRJbWFnZWAgZGlyZWN0aXZlLiBJdCBpcyBlbm91Z2ggdG8gc3BlY2lmeSBhIFVSTCBidWlsZGVyIGZ1bmN0aW9uIHRvIG9idGFpbiBmdWxsIERJXG4gKiBjb25maWd1cmF0aW9uIGZvciBhIGdpdmVuIGxvYWRlcjogYSBESSB0b2tlbiBjb3JyZXNwb25kaW5nIHRvIHRoZSBhY3R1YWwgbG9hZGVyIGZ1bmN0aW9uLCBwbHVzIERJXG4gKiB0b2tlbnMgbWFuYWdpbmcgcHJlY29ubmVjdCBjaGVjayBmdW5jdGlvbmFsaXR5LlxuICogQHBhcmFtIGJ1aWxkVXJsRm4gYSBmdW5jdGlvbiByZXR1cm5pbmcgYSBmdWxsIFVSTCBiYXNlZCBvbiBsb2FkZXIncyBjb25maWd1cmF0aW9uXG4gKiBAcGFyYW0gZXhhbXBsZVVybHMgZXhhbXBsZSBvZiBmdWxsIFVSTHMgZm9yIGEgZ2l2ZW4gbG9hZGVyICh1c2VkIGluIGVycm9yIG1lc3NhZ2VzKVxuICogQHJldHVybnMgYSBzZXQgb2YgREkgcHJvdmlkZXJzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNvbmZpZ3VyZWQgaW1hZ2UgbG9hZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVJbWFnZUxvYWRlcihcbiAgYnVpbGRVcmxGbjogKHBhdGg6IHN0cmluZywgY29uZmlnOiBJbWFnZUxvYWRlckNvbmZpZykgPT4gc3RyaW5nLFxuICBleGFtcGxlVXJscz86IHN0cmluZ1tdLFxuKSB7XG4gIHJldHVybiBmdW5jdGlvbiBwcm92aWRlSW1hZ2VMb2FkZXIocGF0aDogc3RyaW5nKSB7XG4gICAgaWYgKCFpc1ZhbGlkUGF0aChwYXRoKSkge1xuICAgICAgdGhyb3dJbnZhbGlkUGF0aEVycm9yKHBhdGgsIGV4YW1wbGVVcmxzIHx8IFtdKTtcbiAgICB9XG5cbiAgICAvLyBUaGUgdHJhaWxpbmcgLyBpcyBzdHJpcHBlZCAoaWYgcHJvdmlkZWQpIHRvIG1ha2UgVVJMIGNvbnN0cnVjdGlvbiAoY29uY2F0ZW5hdGlvbikgZWFzaWVyIGluXG4gICAgLy8gdGhlIGluZGl2aWR1YWwgbG9hZGVyIGZ1bmN0aW9ucy5cbiAgICBwYXRoID0gbm9ybWFsaXplUGF0aChwYXRoKTtcblxuICAgIGNvbnN0IGxvYWRlckZuID0gKGNvbmZpZzogSW1hZ2VMb2FkZXJDb25maWcpID0+IHtcbiAgICAgIGlmIChpc0Fic29sdXRlVXJsKGNvbmZpZy5zcmMpKSB7XG4gICAgICAgIC8vIEltYWdlIGxvYWRlciBmdW5jdGlvbnMgZXhwZWN0IGFuIGltYWdlIGZpbGUgbmFtZSAoZS5nLiBgbXktaW1hZ2UucG5nYClcbiAgICAgICAgLy8gb3IgYSByZWxhdGl2ZSBwYXRoICsgYSBmaWxlIG5hbWUgKGUuZy4gYC9hL2IvYy9teS1pbWFnZS5wbmdgKSBhcyBhbiBpbnB1dCxcbiAgICAgICAgLy8gc28gdGhlIGZpbmFsIGFic29sdXRlIFVSTCBjYW4gYmUgY29uc3RydWN0ZWQuXG4gICAgICAgIC8vIFdoZW4gYW4gYWJzb2x1dGUgVVJMIGlzIHByb3ZpZGVkIGluc3RlYWQgLSB0aGUgbG9hZGVyIGNhbiBub3RcbiAgICAgICAgLy8gYnVpbGQgYSBmaW5hbCBVUkwsIHRodXMgdGhlIGVycm9yIGlzIHRocm93biB0byBpbmRpY2F0ZSB0aGF0LlxuICAgICAgICB0aHJvd1VuZXhwZWN0ZWRBYnNvbHV0ZVVybEVycm9yKHBhdGgsIGNvbmZpZy5zcmMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYnVpbGRVcmxGbihwYXRoLCB7Li4uY29uZmlnLCBzcmM6IG5vcm1hbGl6ZVNyYyhjb25maWcuc3JjKX0pO1xuICAgIH07XG5cbiAgICBjb25zdCBwcm92aWRlcnM6IFByb3ZpZGVyW10gPSBbe3Byb3ZpZGU6IElNQUdFX0xPQURFUiwgdXNlVmFsdWU6IGxvYWRlckZufV07XG4gICAgcmV0dXJuIHByb3ZpZGVycztcbiAgfTtcbn1cblxuZnVuY3Rpb24gdGhyb3dJbnZhbGlkUGF0aEVycm9yKHBhdGg6IHVua25vd24sIGV4YW1wbGVVcmxzOiBzdHJpbmdbXSk6IG5ldmVyIHtcbiAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihcbiAgICBSdW50aW1lRXJyb3JDb2RlLklOVkFMSURfTE9BREVSX0FSR1VNRU5UUyxcbiAgICBuZ0Rldk1vZGUgJiZcbiAgICAgIGBJbWFnZSBsb2FkZXIgaGFzIGRldGVjdGVkIGFuIGludmFsaWQgcGF0aCAoXFxgJHtwYXRofVxcYCkuIGAgK1xuICAgICAgICBgVG8gZml4IHRoaXMsIHN1cHBseSBhIHBhdGggdXNpbmcgb25lIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0czogJHtleGFtcGxlVXJscy5qb2luKFxuICAgICAgICAgICcgb3IgJyxcbiAgICAgICAgKX1gLFxuICApO1xufVxuXG5mdW5jdGlvbiB0aHJvd1VuZXhwZWN0ZWRBYnNvbHV0ZVVybEVycm9yKHBhdGg6IHN0cmluZywgdXJsOiBzdHJpbmcpOiBuZXZlciB7XG4gIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgUnVudGltZUVycm9yQ29kZS5JTlZBTElEX0xPQURFUl9BUkdVTUVOVFMsXG4gICAgbmdEZXZNb2RlICYmXG4gICAgICBgSW1hZ2UgbG9hZGVyIGhhcyBkZXRlY3RlZCBhIFxcYDxpbWc+XFxgIHRhZyB3aXRoIGFuIGludmFsaWQgXFxgbmdTcmNcXGAgYXR0cmlidXRlOiAke3VybH0uIGAgK1xuICAgICAgICBgVGhpcyBpbWFnZSBsb2FkZXIgZXhwZWN0cyBcXGBuZ1NyY1xcYCB0byBiZSBhIHJlbGF0aXZlIFVSTCAtIGAgK1xuICAgICAgICBgaG93ZXZlciB0aGUgcHJvdmlkZWQgdmFsdWUgaXMgYW4gYWJzb2x1dGUgVVJMLiBgICtcbiAgICAgICAgYFRvIGZpeCB0aGlzLCBwcm92aWRlIFxcYG5nU3JjXFxgIGFzIGEgcGF0aCByZWxhdGl2ZSB0byB0aGUgYmFzZSBVUkwgYCArXG4gICAgICAgIGBjb25maWd1cmVkIGZvciB0aGlzIGxvYWRlciAoXFxgJHtwYXRofVxcYCkuYCxcbiAgKTtcbn1cbiJdfQ==