В экосистеме Remark и Rehype совместимость со старыми плагинами является критическим аспектом, обеспечивающим плавный переход на новые версии и позволяющим использовать существующие наработки без полной переработки кода. Основной механизм совместимости строится на строгом соблюдении стандартов AST (Abstract Syntax Tree) и унификации API плагинов.
Remark использует собственный формат AST, известный как MDAST (Markdown Abstract Syntax Tree). Для Rehype применяется HAST (Hypertext Abstract Syntax Tree). Ключевой принцип совместимости заключается в неизменности базовых узлов и их свойств:
type) должны сохраняться.
Например, heading, paragraph,
text.children) обязана соответствовать ожидаемому формату.
Любое нарушение приводит к ошибкам у старых плагинов.data,
position) добавляются только в новые версии узлов, не
удаляя или изменяя существующие.Для старых плагинов важно, чтобы новые версии библиотек не изменяли именование базовых типов и порядок дочерних элементов, иначе плагин перестанет корректно работать.
Remark и Rehype предоставляют плагинам единый интерфейс через функцию-обработчик. Совместимость обеспечивается следующими принципами:
(options?: object) => Transformer, продолжают
работать, даже если в новой версии добавлены дополнительные
необязательные параметры.(tree, file) => void | Promise<void>.
Любые изменения типа возвращаемого значения могут нарушить работу
старого плагина.Для плагинов, разработанных под ранние версии Remark или Rehype, можно использовать адаптеры, которые обеспечивают преобразование AST и корректную работу API:
(tree, file, next) => { ... }, что обеспечивает
совместимость с современным движком Remark/Rehype.function oldHeadingPlugin() {
return (tree) => {
visit(tree, 'heading', (node) => {
node.value = node.value.toUpperCase();
});
};
}
В новых версиях Remark node может иметь поле children
вместо value. Адаптер преобразует структуру:
function headingAdapterPlugin(oldPlugin) {
return (tree) => {
const adaptedTree = adaptTreeForOldPlugin(tree);
oldPlugin()(adaptedTree);
mergeTreeChanges(tree, adaptedTree);
};
}
Старые плагины были синхронными, но их можно использовать в
remark().use(asyncPlugin), оборачивая старую функцию в
Promise.resolve().
Для гарантии стабильной работы старых плагинов рекомендуется проводить тестирование:
remark-parse,
remark-stringify, rehype-stringify.data для совместимости с
плагинами, не использующими новые поля.Соблюдение этих правил позволяет поддерживать экосистему Remark и Rehype, одновременно развивая функциональность библиотек и сохраняя совместимость с существующими плагинами.