UNPKG

@angular/common

Version:

Angular - commonly needed directives and services

74 lines 12.3 kB
/** * @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