I am looking for a way to display text (markdown) on page that can contain a fontawesome icon. The framework is Angular 15 and fortawesome 6 has been used.
The text is dynamically inserted through an innerHTML
tag.
Through a markdown pipe I was able to convert the text (in markdown) to semantically correct HTML. Unfortunately, regarding the parse of the icons, I have not found a good solution for the moment. What I don't understand is, how do I prevent ng/security#xss
from cleaning up my code and simultaneously have the icon placeholder convert to call the fontawesome component and display it?
I tried using
content.replace(/{!!icon!!}/g, '<fa-icon [icon]="faCoffee"></fa-icon>')
to replace the placeholder {!!icon!!}
with the icon. However, Angular's security intervenes and kills the <fa-icon [icon]="faCoffee"></fa-icon>
. So I attempted to use return this.domSanitizer.bypassSecurityTrustHtml
in pipe to prevent the ng/security#xss
from killing my code. This works but the icon is not displayed because the code <fa-icon [icon]="faCoffee"></fa-icon>
is not interpreted.
@Pipe({
name: 'sanitizer'
})
export class SanitizerPipe implements PipeTransform {
constructor(private domSanitizer: DomSanitizer) { }
transform(content: string, ...args: unknown[]): unknown {
return this.domSanitizer.bypassSecurityTrustHtml(this.iconParser(content)) as SafeHtml;
}
}
private iconParser = (content: string) => {
return content.replace(/{!!icon!!}/g, `<fa-icon [icon]="faCoffee"></fa-icon>`);
}
}
I saw a question asked quite some time ago they had solved by injecting the fontawesome component. So my approach is easily wrong, however I have no idea how I could solve it with this.
Angular's unnecessarily complicated "documentation"(API), says nothing on this topic, as usual.
This particular problem is solved directly by Fontawesome through this guide. The library (angular-fontawesome) provides the function icon()
. This solves the problem as you just need to do:
import { icon } from '@fortawesome/fontawesome-svg-core';
...
private iconParser = (content: string) => {
return content.replace(/{!!icon!!}/g, `${icon(faCoffee).html.join('')}`);
}
The icon(faCoffee).html.join('')
code generates a valid SVG:
<svg aria-hidden="true" focusable="false" ... ><path fill="currentColor" ...></path></svg>