Библиотеки Remark и Rehype строятся на основе экосистемы unified, которая предоставляет унифицированный способ обработки документов через абстрактное синтаксическое дерево (AST). Понимание архитектуры плагинов является ключевым для эффективного использования этих инструментов.
Плагин в unified — это функция, которая принимает опции и возвращает либо функцию трансформации AST, либо объект с методами для модификации дерева. Основные типы плагинов:
Каждый плагин регистрируется через метод use,
обеспечивая цепочку обработки данных.
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
const processor = unified()
.use(remarkParse)
.use(myCustomPlugin, { option: true })
.use(remarkStringify);
Плагин должен соответствовать следующей структуре:
Строгий контракт позволяет комбинировать плагины в произвольном порядке без потери совместимости.
В Remark используется дерево MDAST (Markdown AST), в
Rehype — HAST (HTML AST). Структура AST схожа: каждый
узел имеет тип (type) и список дочерних узлов
(children). Плагины обычно работают с узлами
рекурсивно.
Пример обхода дерева:
function visitNodes(node, callback) {
callback(node);
if (node.children) {
node.children.forEach(child => visitNodes(child, callback));
}
}
Применение:
visitNodes(tree, node => {
if (node.type === 'heading') {
node.depth += 1; // увеличить уровень заголовка
}
});
Плагины принимают опции, позволяя настраивать поведение:
true / false){ level: 2, prefix: '!' })Например, плагин для добавления якорей к заголовкам может принимать функцию генерации идентификатора:
function remarkAddAnchors(options = {}) {
return (tree) => {
visitNodes(tree, node => {
if (node.type === 'heading') {
node.data = node.data || {};
node.data.id = options.generateId
? options.generateId(node)
: node.children.map(c => c.value).join('-').toLowerCase();
}
});
};
}
Unifed строит цепочку плагинов, где каждый следующий получает AST после предыдущего. Это обеспечивает:
unified()
.use(remarkParse)
.use(pluginA)
.use(pluginB, { option: 123 })
.use(remarkStringify);
Стандартный паттерн — использование visitor-функций для обхода дерева:
import { visit } from 'unist-util-visit';
visit(tree, 'link', node => {
node.url = node.url.replace('http://', 'https://');
});
Преимущества:
heading,
paragraph, link)childrenПлагины могут:
footnote)Эти возможности делают unified гибкой платформой для построения сложных пайплайнов обработки текста.
Эта архитектура позволяет строить сложные цепочки обработки текста, объединяя разбор, трансформацию и генерацию конечного формата через модульные и легко тестируемые плагины. Remark и Rehype используют этот подход для работы с Markdown и HTML, делая unified универсальным инструментом для любых текстовых преобразований.