MDX (Markdown for JSX) объединяет синтаксис Markdown и возможности JSX, позволяя включать компоненты React прямо в документы Markdown. Для понимания и модификации MDX-документов на глубоком уровне используется AST (Abstract Syntax Tree) — абстрактное синтаксическое дерево, которое представляет структуру документа.
AST в MDX строится на основе двух уровней:
MDX парсер сначала строит MDAST, затем преобразует его в HAST, где JSX-компоненты интегрируются в дерево как специальные узлы. Этот процесс позволяет выполнять сложные трансформации и анализ документов на уровне синтаксиса.
Каждый узел AST имеет обязательное поле type,
определяющее его роль. Основные типы узлов в MDX:
children.children
содержит текстовые или встроенные узлы.depth задаёт
уровень (1-6), children — текст.value.lang и
value.value.url и
children.Пример AST узла параграфа:
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Пример текста в параграфе"
}
]
}
MDX интегрируется с экосистемой unified, что позволяет использовать цепочку плагинов:
Пример обхода и изменения всех заголовков уровня 2:
import { visit } from 'unist-util-visit';
visit(ast, 'heading', (node) => {
if (node.depth === 2) {
node.children.push({ type: 'text', value: ' (обновлено)' });
}
});
Вставка компонентов React в MDX выполняется через узлы типа
jsx. Для добавления компонента в документ:
import { u } from 'unist-builder';
const jsxNode = u('jsx', { value: '<MyComponent prop="value" />' });
ast.children.push(jsxNode);
MDX автоматически обрабатывает JSX при рендеринге, если узел
правильно встроен в AST. При этом важно учитывать, что JSX узлы
находятся на этапе HAST, поэтому для сложных трансформаций может
потребоваться использование mdxjs/mdx с включением
опции rehypePlugins.
Трансформации делятся на несколько типов:
Пример фильтрации всех комментариев из документа:
import { visit } from 'unist-util-visit';
visit(ast, 'html', (node, index, parent) => {
if (node.value.startsWith('<!--')) {
parent.children.splice(index, 1);
}
});
children для
корректного синтаксиса.node.type, чтобы случайно не изменить неподходящий
узел.console.log(JSON.stringify(ast, null, 2))
для визуализации дерева.remark-mdx и визуально видеть результат парсинга.unist-util-visit или
unist-util-visit-parents для селективной модификации.MDX AST предоставляет гибкий способ анализа и модификации документов, позволяя интегрировать динамический JSX в Markdown, создавать кастомные трансформации и полностью контролировать структуру контента.