В экосистеме Remark и Rehype основой обработки Markdown и HTML являются деревья AST (Abstract Syntax Tree), где каждый элемент представлен узлом. Разделение узлов по типам позволяет точно управлять структурой документа и выполнять трансформации контента на различных уровнях. Понимание типов узлов критично для эффективного использования плагинов и написания собственных обработчиков.
Remark оперирует деревом, называемым MDAST (Markdown Abstract Syntax Tree). Основные категории узлов:
Документные узлы (root)
Представляют весь документ Markdown.
Содержат в себе массив дочерних узлов (children),
которые могут быть параграфами, заголовками, списками и так
далее.
Пример:
{
type: 'root',
children: [/* параграфы, заголовки, списки */]
}Блочные узлы (block)
Определяют структурные элементы документа:
paragraph — параграф текста.heading — заголовок, с уровнем (depth) от
1 до 6.blockquote — блок цитаты.list — список, с параметрами ordered и
start.listItem — элемент списка.thematicBreak — горизонтальная линия.Пример узла заголовка:
{
type: 'heading',
depth: 2,
children: [
{ type: 'text', value: 'Подзаголовок' }
]
}Инлайновые узлы (inline)
Содержимое внутри блочных узлов:
text — простой текст.emphasis — выделение курсивом.strong — жирное выделение.inlineCode — встроенный код.link — ссылка, с атрибутами url и
title.image — изображение.Пример узла ссылки:
{
type: 'link',
url: 'https://example.com',
title: 'Пример',
children: [{ type: 'text', value: 'Перейти на сайт' }]
}Дополнительные узлы
code — блочный код, с языком (lang) и
текстом (value).html — произвольный HTML-контент.definition и footnote — для ссылок и
сносок.Rehype работает с HAST (HTML Abstract Syntax Tree), где узлы представляют элементы HTML. Основные типы узлов:
Элементные узлы (element)
Соответствуют тегам HTML.
Атрибуты хранятся в объекте properties.
Дочерние узлы находятся в массиве children.
Пример узла:
{
type: 'element',
tagName: 'p',
properties: {},
children: [
{ type: 'text', value: 'Текст параграфа' }
]
}Текстовые узлы (text)
Содержат текстовое содержимое элементов.
Не имеют дочерних узлов.
Пример:
{ type: 'text', value: 'Простой текст' }Комментарий (comment)
Содержит комментарий HTML.
Пример:
{ type: 'comment', value: 'Это комментарий' }Документные узлы
root — корневой узел, аналогичный Remark.doctype — для указания типа документа.Прочие узлы
raw — сырые HTML-фрагменты.element с атрибутом data используется для
расширений и кастомных плагинов.Для конвертации Markdown в HTML часто используют цепочку:
remark → rehype → stringify. В этом процессе:
MDAST трансформируется в HAST, при этом каждый блочный и инлайновый узел получает HTML-аналог.
paragraph → pheading → h1-h6strong → strongemphasis → emПонимание типов узлов важно при написании плагинов, например:
link на кастомные компоненты.Каждый узел имеет обязательное свойство
type.
Узлы могут содержать массив children или строку
value, в зависимости от типа.
Разделение на блочные и инлайновые позволяет рекурсивно обходить дерево, не нарушая структуры.
Некоторые узлы имеют дополнительные свойства, специфичные для конкретного типа, например:
depth у заголовка.lang у кода.url и title у ссылок.ordered и start у списков.Для безопасной работы с деревом используются методы обхода, такие
как unist-util-visit, которые позволяют выбирать узлы по
типу и производить трансформации.
Фильтрация текста:
import { visit } from 'unist-util-visit';
visit(tree, 'text', node => {
node.value = node.value.replace(/example/g, 'пример');
});Добавление CSS-классов к элементам:
visit(tree, 'element', node => {
if (node.tagName === 'h2') {
node.properties.className = ['section-title'];
}
});Генерация оглавления на основе узлов heading с
уровнем depth:
const toc = [];
visit(tree, 'heading', node => {
toc.push({ depth: node.depth, title: node.children[0].value });
});Эта классификация узлов формирует основу для глубокого понимания работы Remark и Rehype, позволяя создавать сложные плагины и трансформации документов, управлять содержимым на уровне структуры и текста, а также эффективно комбинировать Markdown и HTML.