Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - innerHTML, escape less/greater than characters, but leave <br /> untouched

So I have an Angular 8 app with a table that is displaying parsed XML content, but there are some cases where a string can contain
tags that needs to be parsed as HTML, but also other content braced in less/greater than signs, for example . I'm using [innerHTML] to inject it to a tag, but these braced strings get cut out. I've tried using DomSanitizer like this:

public sanitizeDsxText(text: any): any {
    return this.sanitizer.bypassSecurityTrustHtml(text);
}

But unfortunately, that didn't work either. Have anyone ever faced a similar issue and can provide a simple solution? I will appreciate it greatly :),

EDIT: As per request, to be more precise. I have a like this:

<td class="dsx-table__cell" [innerHTML]="item.target?.txt">
</td>

Text in "item.target?.txt" looks like this: "Cześć wam, tu bliźniaki dwa <br/> Paprika – siostra, brat <FAR/OFF>" *

  • tags with added spaces because StackOverflow is cutting them too.

And the <bt/> get parsed like it should, to normal <br> tag, but <FAR/OFF> get cut out - I need to find a way to only parse <br>'s and leave other strings in brackets not parsed.

like image 219
grhu Avatar asked Aug 09 '19 11:08

grhu


People also ask

Is it safe to use innerHtml in angular?

Yes, it's safe.

Does angular escape HTML?

Angular automatically escapes data if you use ng-bind or the {{ curly brace syntax }} . This means it outputs the literal characters instead of interpreting them as HTML.

What is innerHtml in angular?

The innerHtml attribute is a standard HTML element attribute to which Angular 14 can bind with square brackets i.e [ & ] .


1 Answers

I'm late to the party. I've created a Angular pipe that either allows you to selectively allow tags or have the option to convert them to HTML entities.

Here's the code:

import { Pipe, PipeTransform } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";
import DOMPurify from "dompurify";

@Pipe({
  name: "safeHtml",
})
export class SafeHtmlPipe implements PipeTransform {
  constructor(private domSanitizer: DomSanitizer) {
    // How to securely allow target attribute
    // https://github.com/cure53/DOMPurify/issues/317
    DOMPurify.addHook("afterSanitizeAttributes", function (node: Element) {
      // set all elements owning target to target=_blank
      if ("target" in node) {
        (node as Element).setAttribute("target", "_blank");
        (node as Element).setAttribute("rel", "noopener");
      }
    });
  }

  transform(html: string, convertToEntity: boolean, additionalTags?: string[]): string {
    if (html.length > 0) {
      // we don't want tags such as `<input>` or any form elements
      // from being displayed, and at the same time allows certain
      // tags element for styling
      const sanitizeOptions = {
        FORBID_TAGS: ["script", "form", "input", "select", "textarea"],
        ADD_TAGS: ["b", "i", "em", "span"],
        ALLOW_UNKNOWN_PROTOCOLS: true,
        // NOTE: we enable this one if in case the addHook method has unexpected behavior
        // ADD_ATTR: ["target"],
      };

      if (additionalTags && additionalTags.length) {
        sanitizeOptions.ADD_TAGS.push(...additionalTags);
      }

      let sanitizedContent = html;

      if (convertToEntity) {
        sanitizedContent = this.escapeHtml(html);
      } else {
        sanitizedContent = DOMPurify.sanitize(html, sanitizeOptions);
      }

      return this.domSanitizer.bypassSecurityTrustHtml(sanitizedContent) as string;
    }

    return html;
  }

  private escapeHtml(str: string): string {
    // DOMSanitizer or DOMPurify doesn't have options to convert special characters
    // to html entities
    return str
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#039;");
  }
}

Usage:

  • allow img and a tags
<div class="modal-body" [innerHTML]="message | safeHtml: false:['img', 'a']"></div>
  • escape strings by converting special characters to their equivalent HTML entities. Useful for displaying codes as string without the fear for XSS
<p [innerHTML]="content | safeHtml: true"></p>
like image 62
The.Wolfgang.Grimmer Avatar answered Sep 27 '22 20:09

The.Wolfgang.Grimmer