В экосистеме Remark и Rehype каждый документ представляется в виде дерева абстрактного синтаксиса (AST). Узлы AST имеют определённые типы, соответствующие элементам Markdown, HTML или другим форматам. Однако для сложных задач обработки текста стандартного набора типов может быть недостаточно. Здесь вступает в силу возможность расширения типов узлов, что позволяет создавать собственные структуры и обогащать AST дополнительной информацией.
Тип узла (type) Каждому узлу AST
соответствует строковый идентификатор типа, например,
paragraph, heading, link. Для
создания собственного узла необходимо определить уникальное имя типа.
Например:
const customNode = {
type: 'fancyBox',
title: 'Важное сообщение',
content: 'Текст внутри коробки'
};Структура узла Узлы могут содержать стандартные
поля children для вложенных элементов и дополнительные поля
для хранения информации, специфичной для конкретного расширения.
Например:
{
type: 'tooltip',
text: 'Наведи на меня',
children: [
{ type: 'text', value: 'Информация о подсказке' }
]
}Совместимость с процессорами Расширенные узлы должны корректно интегрироваться с плагинами Remark или Rehype. Для этого рекомендуется:
Плагины Remark и Rehype позволяют изменять дерево AST во время
парсинга или трансформации. Пример плагина для добавления узла
fancyBox:
import { visit } from 'unist-util-visit';
function remarkFancyBox() {
return (tree) => {
visit(tree, 'paragraph', (node, index, parent) => {
if (node.children.some(child => child.value.includes('[box]'))) {
const content = node.children.map(child => child.value).join(' ').replace('[box]', '');
parent.children[index] = {
type: 'fancyBox',
title: 'Box',
content,
children: []
};
}
});
};
}
Здесь:
visit из
unist-util-visit для обхода AST.[box].fancyBox.Для Rehype узлы представляют собой HTML-структуры. Расширение типов может использоваться для добавления семантических элементов или нестандартных атрибутов:
const customElement = {
type: 'element',
tagName: 'highlight',
properties: { color: 'yellow' },
children: [
{ type: 'text', value: 'Выделенный текст' }
]
};
type: 'element' — стандартный Rehype-тип для
HTML-элементов.tagName — имя тега, которое может быть
нестандартным.properties — объект с атрибутами HTML.children — массив вложенных узлов.Для обработки таких элементов создаются плагины Rehype, которые могут преобразовывать новые узлы в стандартный HTML или другой формат:
function rehypeHighlight() {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'highlight') {
node.tagName = 'span';
node.properties.style = `background-color: ${node.properties.color}`;
}
});
};
}
После расширения типов узлов важно корректно обрабатывать их при конвертации в Markdown или HTML:
remark-stringify необходимо определить, как новый узел
превращается в Markdown. Обычно для этого создаются функции-конвертеры,
которые возвращают массив стандартных узлов или текст.rehype-stringify новые элементы преобразуются в HTML через
tagName и properties.myPlugin/fancyBox, чтобы избегать конфликтов с другими
плагинами.Расширение типов узлов предоставляет мощный инструмент для создания кастомных форматов, внедрения семантики и специализированных трансформаций документов. Благодаря гибкости Remark и Rehype можно строить сложные редакторы, генераторы документации и конвертеры, полностью управляя структурой AST.