Разрешение HTML в markdown

Markdown-it — это мощная библиотека для преобразования текста в формате Markdown в HTML. Одной из её ключевых особенностей является поддержка встроенного HTML, что позволяет расширять возможности Markdown за пределы стандартного синтаксиса.

Включение и отключение HTML

По умолчанию Markdown-it поддерживает HTML внутри текста. Включение и отключение этой функции осуществляется через опцию html при создании экземпляра парсера:

const MarkdownIt = require('markdown-it');
const md = new MarkdownIt({
  html: true,  // разрешение HTML
  linkify: true,
  typographer: true
});

Если значение опции html установить в false, все HTML-теги будут экранированы и отображены как обычный текст:

const mdNoHtml = new MarkdownIt({ html: false });
console.log(mdNoHtml.render('<b>Привет</b>')); 
// &lt;b&gt;Привет&lt;/b&gt;

Особенности обработки HTML

Markdown-it обрабатывает HTML следующим образом:

  1. Блочные элементы<div>, <table>, <pre>, <section> и другие, размещённые на отдельной строке, распознаются как отдельные блоки. Markdown внутри таких блоков не интерпретируется.
  2. Строчные элементы<span>, <a>, <strong> и другие, включённые внутрь строки текста, отображаются в месте их вставки без изменения содержимого.
  3. Смешанный контент — HTML и Markdown могут комбинироваться. Например, внутри <div> можно вставлять списки или заголовки, но Markdown внутри некоторых элементов (например, <pre> или <code>) игнорируется.

Настройка разрешения HTML через плагины

Markdown-it поддерживает плагины, которые могут управлять безопасностью и обработкой HTML:

  • markdown-it-sanitizer — позволяет фильтровать нежелательные теги и атрибуты.
  • markdown-it-container — создаёт настраиваемые контейнеры, которые могут содержать HTML.

Пример использования фильтрации HTML:

const MarkdownIt = require('markdown-it');
const md = new MarkdownIt({ html: true });
const sanitizeHtml = require('sanitize-html');

md.renderer.rules.html_block = (tokens, idx) => {
  const content = tokens[idx].content;
  return sanitizeHtml(content, {
    allowedTags: ['b', 'i', 'strong', 'em', 'a'],
    allowedAttributes: { 'a': ['href'] }
  });
};

const result = md.render('<script>alert("XSS")</script><b>Bold</b>');
console.log(result); // <b>Bold</b>

В этом примере все опасные HTML-теги, такие как <script>, удаляются, а разрешённые элементы сохраняются.

Безопасность при разрешении HTML

Разрешение HTML открывает возможность внедрения XSS-атак. Для безопасного использования рекомендуется:

  • Отключать HTML для контента от ненадёжных источников (html: false).
  • Использовать библиотеки фильтрации, такие как sanitize-html.
  • Ограничивать список разрешённых тегов и атрибутов.
  • Проверять комбинированное использование Markdown и HTML, чтобы нежелательные элементы не могли обойти фильтры.

Рендеринг HTML в различных режимах

Markdown-it поддерживает два вида HTML:

  1. Блочный HTML (html_block) — отдельные строки, начинающиеся с < и заканчивающиеся >. Рендерится как полноценный блок.
  2. Строчный HTML (html_inline) — включён внутри текста. Не создаёт отдельного блока и интегрируется с Markdown-разметкой.

Пример:

const md = new MarkdownIt({ html: true });

const input = `
Это <span style="color:red">красный текст</span> в строке.

<div>
  <p>Блок HTML с параграфом</p>
</div>
`;

console.log(md.render(input));

В результате <span> отобразится внутри строки, а <div> создаст отдельный блок с параграфом.

Итоговые рекомендации

  • Для контента с доверенными HTML-тегами опция html: true подходит идеально.
  • Для публикации пользовательского контента HTML следует фильтровать или полностью отключать.
  • Markdown-it обеспечивает гибкость, позволяя комбинировать HTML и Markdown, сохраняя при этом контроль над безопасностью и структурой документа.

Использование HTML в Markdown через Markdown-it — мощный инструмент для создания сложных документов и веб-контента с контролем безопасности и структурной гибкости.