From d02525157267d64104c212c09e3d81f28c1d4605 Mon Sep 17 00:00:00 2001 From: Jean Fernandez <55406257+jean-the-coder@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:52:40 -0500 Subject: [PATCH] Prevent possible endless loop with image fallback (#444) --- frontend/.storybook/main.ts | 1 + .../directives/image-fallback.directive.ts | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/frontend/.storybook/main.ts b/frontend/.storybook/main.ts index c55443c5..ac379ce8 100644 --- a/frontend/.storybook/main.ts +++ b/frontend/.storybook/main.ts @@ -1,6 +1,7 @@ import type { StorybookConfig } from "@storybook/angular"; const config: StorybookConfig = { stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + staticDirs: [{ from: '../src/assets', to: '/assets' }], addons: [ "@storybook/addon-links", "@storybook/addon-essentials", diff --git a/frontend/src/app/directives/image-fallback.directive.ts b/frontend/src/app/directives/image-fallback.directive.ts index 1fb52a36..f1c32f4c 100644 --- a/frontend/src/app/directives/image-fallback.directive.ts +++ b/frontend/src/app/directives/image-fallback.directive.ts @@ -1,5 +1,7 @@ import {Directive, ElementRef, HostListener, Input} from '@angular/core'; +const DEFAULT_IMAGE_FALLBACK_PATH: string = '/assets/images/no-image.svg'; + @Directive({ selector: 'img[imageFallback]' }) @@ -10,7 +12,22 @@ export class ImageFallbackDirective { @HostListener('error') loadFallbackOnError() { - this.elementRef.nativeElement.src = this.imageFallback || 'assets/images/no-image.svg'; + // Check to see if we have already tried to load the fallback image. + // Avoids endless loop if for some reason fallback image is missing. Just accept the broken image. + if (this.path(this.elementRef.nativeElement.src) == this.path(this.fallbackSrc())) { + return; + } + + this.elementRef.nativeElement.src = this.fallbackSrc(); + } + + private fallbackSrc(): string { + return this.imageFallback || DEFAULT_IMAGE_FALLBACK_PATH; + } + + private path(urlString: string): string { + // remove http(s) and domain + return urlString.replace(/^https?:\/\/[^\/]*/, ''); } }