Для начала работы с Markdown-it в проекте на React необходимо установить сам пакет и, при необходимости, дополнительные плагины:
npm install markdown-it
После установки создаётся экземпляр Markdown-it, который можно настроить под конкретные требования. Например:
import MarkdownIt from 'markdown-it';
const md = new MarkdownIt({
html: true, // Разрешает HTML-теги в Markdown
linkify: true, // Автоматически превращает URL в ссылки
typographer: true, // Включает типографские преобразования (кавычки, тире)
});
Каждая из этих опций может значительно изменить поведение парсера, поэтому важно понимать, какие из них нужны в приложении.
Для интеграции с React чаще всего создают компонент, который принимает Markdown-текст и рендерит HTML. Пример такого компонента:
import React from 'react';
import MarkdownIt from 'markdown-it';
const md = new MarkdownIt({ html: true, linkify: true, typographer: true });
const MarkdownRenderer = ({ content }) => {
const renderedHTML = md.render(content);
return (
<div dangerouslySetInnerHTML={{ __html: renderedHTML }} />
);
};
export default MarkdownRenderer;
Ключевой момент: использование
dangerouslySetInnerHTML необходимо для вывода HTML,
сгенерированного Markdown-it. Это открывает потенциальные риски XSS,
поэтому важно убедиться в безопасном содержимом или использовать
фильтры.
Markdown-it имеет развитую систему плагинов, расширяющих возможности парсера. Примеры популярных плагинов:
import MarkdownIt from 'markdown-it';
import markdownItAnchor from 'markdown-it-anchor';
const md = new MarkdownIt();
md.use(markdownItAnchor, {
permalink: markdownItAnchor.permalink.ariaHidden({ symbol: '#' }),
level: [1, 2, 3],
});
import markdownItFootnote from 'markdown-it-footnote';
md.use(markdownItFootnote);
import markdownItContainer from 'markdown-it-container';
md.use(markdownItContainer, 'warning', {
render(tokens, idx) {
if (tokens[idx].nesting === 1) {
return '<div class="warning">';
} else {
return '</div>';
}
}
});
Каждый плагин подключается методом .use() и может
принимать собственные параметры для кастомизации рендеринга.
Для защиты от XSS рекомендуется использовать библиотеку
DOMPurify совместно с Markdown-it:
import DOMPurify from 'dompurify';
const safeHTML = DOMPurify.sanitize(md.render(content));
return <div dangerouslySetInnerHTML={{ __html: safeHTML }} />;
Это особенно важно при отображении контента, введённого пользователями.
Markdown-it поддерживает синхронный рендеринг, но при интеграции с React иногда требуется подготовка контента на сервере:
export async function getStaticProps() {
const fs = require('fs');
const path = require('path');
const fileContent = fs.readFileSync(path.join(process.cwd(), 'content.md'), 'utf-8');
const md = new MarkdownIt();
const htmlContent = md.render(fileContent);
return { props: { htmlContent } };
}
Использование такого подхода позволяет генерировать HTML заранее, сокращая нагрузку на клиент.
Markdown-it предоставляет возможность переопределять рендеринг отдельных элементов. Например, кастомный рендеринг ссылок и изображений:
const defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
tokens[idx].attrPush(['target', '_blank']); // открытие в новой вкладке
tokens[idx].attrPush(['rel', 'noopener noreferrer']);
return defaultRender(tokens, idx, options, env, self);
};
Такой подход позволяет интегрировать Markdown-it в React-проекты с соблюдением требований безопасности и UX.
Для сложных интерфейсов можно создавать компоненты React, которые рендерят отдельные Markdown-блоки, например:
const CustomBlock = ({ content }) => (
<section className="custom-block">
<MarkdownRenderer content={content} />
</section>
);
Это облегчает повторное использование Markdown-контента и упрощает стилизацию с помощью CSS или CSS-in-JS.
Markdown-it поддерживает расширения синтаксиса GitHub-Flavored Markdown через плагины:
import markdownItEmoji from 'markdown-it-emoji';
import markdownItTaskLists from 'markdown-it-task-lists';
md.use(markdownItEmoji);
md.use(markdownItTaskLists, { enabled: true });
Это позволяет отображать emoji, чекбоксы и другие элементы в стиле GitHub прямо в React-приложении.
Для больших документов рекомендуется:
useMemo в React-компонентах:import { useMemo } from 'react';
const renderedHTML = useMemo(() => md.render(content), [content]);
Для вставки изображений, видео или других медиа можно расширять Markdown через контейнеры или кастомные синтаксисы, обрабатываемые плагинами. Пример кастомного рендерера видео:
md.renderer.rules.video = function(tokens, idx) {
const src = tokens[idx].attrGet('src');
return `<video controls src="${src}"></video>`;
};
Это позволяет интегрировать мультимедийный контент без нарушения структуры React-приложения.
Для полного контроля можно преобразовывать Markdown в React-элементы,
минуя dangerouslySetInnerHTML, используя парсинг
токенов:
const renderTokens = (tokens) => tokens.map((token, idx) => {
if (token.type === 'paragraph_open') return <p key={idx} />;
if (token.type === 'inline') return token.content;
if (token.type === 'paragraph_close') return </p>;
});
Этот способ сложнее, но позволяет использовать все преимущества React и избежать проблем с безопасностью.