Библиотеки Remark и Rehype образуют мощный стек для работы с Markdown и HTML в экосистеме JavaScript. Основная цель при работе с MDX — преобразовать текст в абстрактное синтаксическое дерево (AST), которое позволяет анализировать, модифицировать и преобразовывать контент.
MDX объединяет возможности Markdown и JSX. При парсинге MDX важно учитывать как стандартные элементы Markdown, так и JSX-компоненты, встроенные в текст.
npm install remark remark-parse remark-mdx rehype rehype-parse unified
Пример подключения в коде:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkMdx from 'remark-mdx';
import rehype from 'rehype';
import rehypeParse from 'rehype-parse';
Создание MDAST начинается с построения процессора:
const processor = unified()
.use(remarkParse) // Парсер стандартного Markdown
.use(remarkMdx); // Добавление поддержки MDX
const mdxContent = `
# Заголовок 1
Текст параграфа с **жирным текстом**.
<MyComponent prop="value" />
`;
const tree = processor.parse(mdxContent);
console.log(JSON.stringify(tree, null, 2));
Особенности узлов MDAST:
type — тип узла (heading,
paragraph, text,
mdxJsxFlowElement).children — массив дочерних узлов.value — содержимое текста для узлов типа
text.Пример узла для MDX-компонента:
{
"type": "mdxJsxFlowElement",
"name": "MyComponent",
"attributes": [
{
"type": "mdxJsxAttribute",
"name": "prop",
"value": "value"
}
],
"children": []
}
Чтобы интегрировать HTML-рендеринг, используется remark-rehype — плагин, который преобразует дерево Markdown в дерево HTML:
import remarkRehype from 'remark-rehype';
const htmlTree = unified()
.use(remarkParse)
.use(remarkMdx)
.use(remarkRehype) // Конвертация MDAST в HAST
.parse(mdxContent);
console.log(JSON.stringify(htmlTree, null, 2));
Структура узлов HAST:
type — element, text или
comment.tagName — имя HTML-тега (p,
h1, strong).properties — атрибуты HTML-элемента.children — массив дочерних узлов.MDX позволяет встраивать JSX-компоненты. При парсинге важно учитывать:
mdxJsxFlowElement — блоковые компоненты.mdxJsxTextElement — inline-компоненты внутри
текста.attributes.Пример трансформации:
import { toHast } from 'mdast-util-to-hast';
const hastTree = toHast(tree, {
allowDangerousHtml: true // Сохраняет JSX как raw HTML
});
Одним из преимуществ работы с AST является возможность модификации дерева до генерации HTML. Типичные задачи:
import visit from 'unist-util-visit';
visit(tree, 'heading', node => {
node.data = node.data || {};
node.data.hProperties = { className: 'custom-heading' };
});
visit(tree, 'mdxJsxFlowElement', node => {
if (node.name === 'MyComponent') {
node.type = 'element';
node.tagName = 'div';
node.properties = { className: 'my-component' };
node.children = [{ type: 'text', value: 'Содержимое компонента' }];
}
});
Remark и Rehype поддерживают обширную экосистему плагинов:
id к
заголовкам.Использование:
import remarkSlug from 'remark-slug';
import remarkAutolinkHeadings from 'remark-autolink-headings';
const processor = unified()
.use(remarkParse)
.use(remarkMdx)
.use(remarkSlug)
.use(remarkAutolinkHeadings);
unist-util-visit или
unist-util-visit-parents.Эта система позволяет гибко обрабатывать MDX, обеспечивая полный контроль над деревом документа и интеграцию с HTML и React-компонентами. Использование Remark и Rehype превращает работу с Markdown и MDX из простой генерации HTML в мощный инструмент анализа и трансформации контента.