Remark и Rehype — это экосистемы для работы с Markdown и HTML в виде дерева синтаксического анализа (AST). Любая сложная трансформация в этих библиотеках строится на композиции небольших плагинов, которые последовательно обрабатывают узлы AST. Такой подход позволяет создавать мощные конвейеры обработки контента, где каждый шаг выполняет строго определённую задачу.
Композиция плагинов строится на трёх принципах:
Сложные трансформации часто требуют вложенных проходов по
дереву AST. В Remark/Rehype это реализуется через использование
методов visit или transform. Стандартная
структура плагина выглядит так:
function examplePlugin(options) {
return (tree, file) => {
visit(tree, 'text', (node) => {
if (node.value.includes(options.keyword)) {
node.value = node.value.replace(options.keyword, options.replacement);
}
});
};
}
В более сложных случаях один плагин может создавать
вспомогательные узлы, которые затем обрабатываются
другими плагинами. Например, плагин может выделять цитаты из текста,
превращать их в блоки <blockquote> и добавлять к ним
идентификаторы для ссылок.
Remark и Rehype используют цепочку плагинов, где порядок имеет критическое значение. Например:
import {remark} from 'remark';
import remarkParse from 'remark-parse';
import remarkSlug from 'remark-slug';
import remarkAutolinkHeadings from 'remark-autolink-headings';
import remarkCustom from './remarkCustom.js';
remark()
.use(remarkParse)
.use(remarkSlug)
.use(remarkAutolinkHeadings)
.use(remarkCustom, { keyword: 'TODO', replacement: '✔' })
.processSync(markdown);
Здесь:
remarkParse строит базовое дерево Markdown.remarkSlug добавляет идентификаторы заголовкам.remarkAutolinkHeadings генерирует ссылки на
заголовки.remarkCustom выполняет пользовательскую замену
текста.Если поменять порядок плагинов, результат может измениться, что подчёркивает важность контроля последовательности обработки.
Для сложных сценариев часто применяются условные преобразования в плагинах. Например, в зависимости от уровня заголовка или типа узла можно выбирать разные стратегии обработки:
function conditionalPlugin() {
return (tree) => {
visit(tree, (node) => {
if (node.type === 'heading' && node.depth === 2) {
node.children.push({ type: 'text', value: ' - Важный раздел' });
}
});
};
}
Такой подход позволяет строить динамические трансформации, где один плагин может изменять только часть дерева, а другой — уже работать с результатом изменений.
Remark работает с Markdown, Rehype — с HTML. Для комплексной
обработки используют связывающий слой через
remark-rehype:
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
remark()
.use(remarkParse)
.use(remarkCustom)
.use(remarkRehype)
.use(rehypeStringify)
.processSync(markdown);
Сценарии включают:
<script>).visit и
visitParents для точного контроля над деревом
AST.Комплексная композиция Remark и Rehype превращает обработку текстового контента в управляемый, модульный процесс, позволяющий реализовать любые трансформации — от простых замен до генерации интерактивных HTML-документов.