Как безопасно визуализировать html в реакции?

У меня есть некоторая пользовательская html-разметка из текстовой области, и я бы хотел отобразить ее на другой части экрана. Разметка сохраняется как строка в реквизитах компонента.

Я не хочу использовать опасный метод по понятным причинам. Есть ли такой синтаксический анализатор, как marked, но для html, чтобы он удалял теги script и другие недопустимые html.

Ответ 1

Выполните санитарную обработку html с помощью модуля sanitize-html и визуализируйте очищенную строку, используя опасно SetInnerHTML.

Вы можете создать простой компонент оболочки:

const defaultOptions = {
  allowedTags: [ 'b', 'i', 'em', 'strong', 'a' ],
  allowedAttributes: {
    'a': [ 'href' ]
  },
  allowedIframeHostnames: ['www.youtube.com']
};

const sanitize = (dirty, options) => ({
  __html: sanitizeHtml(
    dirty, 
    options: { ...defaultOptions, ...options }
  )
});

const SanitizeHTML = ({ html, options }) => (
  <div dangerouslySetInnerHTML={sanitize(html, options)} />
);

Использование:

<SanitizeHTML html="<img src=x onerror=alert('img') />" />

Вы также можете использовать ответный-sanitized-html компонент SanitizedHTML, который является оболочкой реагирования вокруг sanitize-html:

<SanitizedHTML
  allowedAttributes={{ 'a': ['href'] }}
  allowedTags={['a']}
  html={ '<a href="http://bing.com/">Bing</a>' }
/>

Ответ 2

Пример, основанный на принятом ответе:

import sanitizeHtml from 'sanitize-html';

const MyComponent = () => {
  dirty = '<a href="my-slug" target="_blank" onClick="evil()">click</a>';
  const clean = sanitizeHtml(dirty, {
    allowedTags: ['b', 'i', 'em', 'strong', 'a'],
    allowedAttributes: {
      a: ['href', 'target']
    }
  });
  return (
    <div 
      dangerouslySetInnerHTML={{__html: clean}}
    />
  );
};

MyComponent отображает div, содержащую ссылку без onClick="evil()":

<a href="my-slug" target="_blank">click</a>

Ответ 3

Могу ли я узнать, как добавить опцию инструмента для UL & OL в "sanitize-html"?