Allowing users to enter arbitrary text and displaying it with innerHTML is dangerous and really requires you to know what you're doing.
I'd say your safest option here (without using innerHTML) is to create a component that parses the string, breaks it into segments with their types and content, and dynamically places template, like:
<ng-container *ngFor="let segment of segments">
<span [ngSwitch]="segment.type">
<ng-container *ngSwitchCase="'bold'"><b>segment.content</b></ng-container>
<ng-container *ngSwitchCase="'link'"><a [href]="segment.data">segment.content</a></ng-container>
<ng-container *ngSwitchDefault>segment.content</ng-container>
</span>
</ng-container>
This template could be expanded to handle italics, underline, or whatever. There are some issues with it (like handling anything nested or multiple tags) but all should be solvable.
your segment model might look like:
interface Segment {
content: string;
type: 'bold'|'text'|'link';
data?: any;
}
and then you need some function that parses your string into these segments. hard to say what your parse function would look like without knowing more about your case, but hopefully this gets you started
a posibly easier and still very safe secondary option is to sanitize or escape your string prior to inserting your own tags based on your custom marks, this way you can safely use innerHTML:
// inject the sanitizer
constructor(private sanitizer: DomSanitizer){ }
// run this on your string to remove unsafe text, then insert your marks so you can safely use innerHTML
sanitize(text: string) {
return this.sanitizer.sanitize(SecurityContext.HTML, text);
}
the sanitizer will actually remove unsafe text, though if you want to keep it and display it as text, you could also escape it like in this question here: Manually sanitize a string