Remark и Rehype — это две библиотеки для обработки текстового контента в формате Markdown и HTML в экосистеме JavaScript. Remark работает с Markdown через представление в виде AST (Abstract Syntax Tree), позволяя анализировать, трансформировать и компилировать Markdown в разные форматы. Rehype выполняет аналогичную роль для HTML. Основная сила этих библиотек заключается в их плагинной архитектуре, которая делает их гибкими и расширяемыми.
Remark строит дерево синтаксического анализа Markdown. Каждый узел дерева имеет тип и свойства. Типы узлов включают:
root — корневой узел документа.paragraph — абзац текста.heading — заголовок (depth указывает
уровень).text — текстовая нода.link — ссылка с атрибутами url и
title.image — изображение с url и
alt.Пример AST для Markdown # Заголовок\nТекст абзаца
выглядит так:
{
"type": "root",
"children": [
{
"type": "heading",
"depth": 1,
"children": [{ "type": "text", "value": "Заголовок" }]
},
{
"type": "paragraph",
"children": [{ "type": "text", "value": "Текст абзаца" }]
}
]
}
Установка библиотек через npm:
npm install remark remark-html rehype rehype-stringify
Простейший пример преобразования Markdown в HTML:
import { remark } from 'remark';
import remarkHtml from 'remark-html';
const markdown = '# Заголовок\nТекст абзаца';
remark()
.use(remarkHtml)
.process(markdown)
.then(file => {
console.log(String(file));
});
Здесь remarkHtml превращает Markdown AST в HTML через
промежуточное дерево.
Плагины позволяют расширять функциональность:
Пример использования нескольких плагинов:
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import remarkHtml from 'remark-html';
const markdown = '## Список задач\n- [x] Выполнено\n- [ ] В процессе';
remark()
.use(remarkGfm)
.use(remarkHtml)
.process(markdown)
.then(file => console.log(String(file)));
Remark и Rehype предоставляют возможности для изменения контента на уровне AST. Например, для добавления CSS-класса к заголовкам можно использовать собственный плагин:
function addClassToHeadings() {
return (tree) => {
visit(tree, 'heading', (node) => {
if (!node.data) node.data = {};
if (!node.data.hProperties) node.data.hProperties = {};
node.data.hProperties.className = 'custom-heading';
});
};
}
remark()
.use(addClassToHeadings)
.use(remarkHtml)
.process('# Заголовок')
.then(file => console.log(String(file)));
visit — утилита из пакета unist-util-visit,
которая позволяет обходить AST и модифицировать узлы по типу.
Часто Markdown нужно превратить в безопасный HTML с дальнейшей обработкой. Для этого Remark и Rehype можно комбинировать через unified:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeSanitize from 'rehype-sanitize';
const markdown = '# Заголовок\n<p>HTML внутри Markdown</p>';
unified()
.use(remarkParse)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeSanitize)
.use(rehypeStringify)
.process(markdown)
.then(file => console.log(String(file)));
Опция allowDangerousHtml разрешает встроенный HTML, а
rehype-sanitize удаляет потенциально опасные теги и
атрибуты, что критично для пользовательского контента.
При работе с пользовательским Markdown и HTML важно:
Преобразование Markdown → AST → Rehype AST → безопасный HTML — стандартный рабочий поток для безопасной обработки контента в приложениях типа блогов или форумов.
rehype-react для генерации React-компонентов из AST.unified().use(parser).use(transformer).process(content)
— основной поток обработки.visit(tree, type, callback) — обход узлов AST.toString(node) — получение текстового содержимого
узла.Объединение Remark и Rehype позволяет создавать мощные конвейеры обработки контента, обеспечивая безопасное и гибкое представление Markdown и HTML в веб-приложениях.