Для использования Marked вместе с DOMPurify необходимо установить обе библиотеки через npm или подключить через CDN. В среде Node.js это делается командой:
npm install marked dompurify jsdom
Для браузера можно подключить через CDN:
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
В Node.js потребуется использовать jsdom для создания виртуального DOM, необходимого DOMPurify:
const { JSDOM } = require('jsdom');
const DOMPurify = require('dompurify')(new JSDOM().window);
const marked = require('marked');
Marked преобразует Markdown в HTML, но этот HTML может содержать
потенциально опасный код, например <script> или
атрибуты onload, onclick. DOMPurify выполняет
санитизацию, удаляя все потенциально опасные элементы,
оставляя безопасный HTML.
Простейший пример:
const markdown = "# Заголовок\n\n<script>alert('XSS');</script>";
const html = marked.parse(markdown);
const safeHtml = DOMPurify.sanitize(html);
console.log(safeHtml);
// <h1>Заголовок</h1>
В этом примере <script> полностью удаляется, а
заголовок сохраняется.
DOMPurify предоставляет гибкие возможности для контроля безопасного HTML. Основные опции:
Пример:
const clean = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'ul', 'li', 'h1', 'h2', 'h3'],
ALLOWED_ATTR: ['href', 'title']
});
Это позволяет точно контролировать, какие элементы Markdown будут видны на странице после преобразования.
Для динамического обновления содержимого страницы HTML, сгенерированного из Markdown, можно использовать:
const container = document.getElementById('content');
const markdownText = "# Новый заголовок\n\n[Ссылка](https://example.com)";
container.innerHTML = DOMPurify.sanitize(marked.parse(markdownText));
Таким образом, любой пользовательский Markdown преобразуется в безопасный HTML, готовый для вставки в DOM.
Marked позволяет создавать собственные рендереры, например для обработки ссылок или картинок:
const renderer = new marked.Renderer();
renderer.link = function(href, title, text) {
return `<a href="${href}" title="${title || ''}" target="_blank" rel="noopener noreferrer">${text}</a>`;
};
const html = marked.parse(markdownText, { renderer });
const safeHtml = DOMPurify.sanitize(html);
Использование кастомного рендерера позволяет:
rel="noopener")DOMPurify также поддерживает фильтрацию URL:
const cleanHtml = DOMPurify.sanitize(html, {
ALLOWED_URI_REGEXP: /^https?:\/\//
});
Это исключает использование jav * ascript: и других
небезопасных схем в ссылках.
React, Vue, Angular: Markdown часто используется для рендеринга контента. Важно применять DOMPurify перед вставкой HTML:
React:
import DOMPurify from 'dompurify';
import { marked } from 'marked';
function MarkdownRenderer({ content }) {
const html = DOMPurify.sanitize(marked.parse(content));
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
Vue:
<template>
<div v-html="safeHtml"></div>
</template>
<script>
import DOMPurify from 'dompurify';
import { marked } from 'marked';
export default {
props: ['content'],
computed: {
safeHtml() {
return DOMPurify.sanitize(marked.parse(this.content));
}
}
}
</script>
Прямое использование v-html или
dangerouslySetInnerHTML безопасно только после санитизации
через DOMPurify.
DOMPurify поддерживает хуки, позволяющие модифицировать HTML перед или после санитизации:
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
if (node.tagName === 'A') {
node.setAttribute('rel', 'noopener noreferrer');
node.setAttribute('target', '_blank');
}
});
Совмещение с кастомным рендерером Marked позволяет полностью контролировать структуру и безопасность HTML.
rel="noopener noreferrer" и
target="_blank" для безопасности.ALLOWED_URI_REGEXP, чтобы исключить
потенциально опасные схемы.Интеграция Marked с DOMPurify обеспечивает безопасное и гибкое отображение Markdown, предотвращая XSS и сохраняя удобство редактирования контента.