Remark и Rehype разработаны с принципом модульности и расширяемости, что позволяет использовать плагины и цепочки обработки Markdown и HTML без необходимости переписывать существующий код при обновлениях библиотек. Обратная совместимость обеспечивается на нескольких уровнях: API, структура узлов (AST) и поведение встроенных плагинов.
Главной гарантией обратной совместимости является стабильность
публичного API. Методы, экспортируемые библиотеками, сохраняют свои
сигнатуры между минорными и патч-версиями. Это означает, что код,
использующий remark().use(plugin) или
rehype().use(plugin), будет продолжать работать после
обновления до следующей минорной версии, при условии, что не
использованы экспериментальные функции.
Пример сохранения совместимости:
import {remark} from 'remark';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
const processor = remark()
.use(remarkParse)
.use(remarkStringify);
const markdown = '# Заголовок';
processor.process(markdown).then(file => {
console.log(String(file));
});
Код выше будет работать в последующих минорных версиях библиотеки,
так как API методов process и цепочки use
сохраняются.
Remark использует unist — универсальный синтаксический деревоподобный формат (Abstract Syntax Tree, AST) для представления Markdown. Rehype использует hast — дерево для HTML. Структура узлов строго документирована, и изменения, которые нарушают совместимость, редки и тщательно обозначаются в релизах.
Ключевые элементы совместимости:
type узла: тип узла сохраняется между версиями
(например, heading, paragraph,
text).children: дочерние узлы остаются массивом, даже если
узлов нет (пустой массив).data и position: поля, используемые
плагинами для хранения метаданных и позиции текста, сохраняются.Пример безопасной модификации AST:
import {visit} from 'unist-util-visit';
visit(tree, 'text', node => {
node.value = node.value.replace(/foo/g, 'bar');
});
Такой подход к модификации узлов останется совместимым в будущих
версиях, так как visit и структура узлов не изменяются.
Remark и Rehype обеспечивают обратную совместимость через стабильное поведение встроенных плагинов, таких как:
remark-parse — разбор Markdownremark-stringify — генерация Markdownrehype-parse — разбор HTMLrehype-stringify — генерация HTMLПлагины поддерживают параметры конфигурации, но старые опции не удаляются без депрецирования и уведомления в changelog. Это позволяет плавно обновлять версии без риска сломать существующие цепочки обработки.
Пример использования конфигурации плагина:
import remark from 'remark';
import remarkHtml from 'remark-html';
remark()
.use(remarkHtml, {sanitize: false}) // старая конфигурация остается поддерживаемой
.process('# Заголовок', (err, file) => {
console.log(String(file));
});
В новых версиях библиотеки устаревшие функции помечаются как deprecated, а использование может генерировать предупреждения в консоли. Это позволяет разработчикам заранее подготовиться к миграции без прерывания работы кода.
Пример обработки deprecated функций:
import remark from 'remark';
import oldPlugin from 'remark-old-plugin';
remark()
.use(oldPlugin) // выведет предупреждение, но останется рабочим
.process('# Тест');
use с отдельными плагинами упрощает замену устаревших
плагинов.Использование этих принципов позволяет создавать устойчивые, легко поддерживаемые системы обработки Markdown и HTML, минимизируя риск нарушения функциональности при обновлениях библиотек.
Обратная совместимость в Remark и Rehype — это не просто удобство, а стратегическая часть их архитектуры, обеспечивающая плавное развитие экосистемы плагинов и стабильность существующих проектов.