Обновление версий unified

Unified — это экосистема инструментов для обработки текста в формате AST (Abstract Syntax Tree) на JavaScript. Две ключевые библиотеки этой экосистемы — Remark (для Markdown) и Rehype (для HTML). Обновление версий этих библиотек требует внимательного подхода, так как каждая новая версия может менять API, внутренние структуры AST и совместимость с плагинами.


Основные принципы обновления

  1. Совместимость с unified Unified придерживается концепции модульной архитектуры. При обновлении Remark или Rehype необходимо проверить, что версия unified в проекте соответствует минимальной версии, требуемой новой версией плагинов. Например, Remark 14.x требует Unified 10.x и выше. Несоответствие может вызвать ошибки при работе processor().use(plugin).

  2. AST и преобразования Remark работает с MDAST (Markdown AST), Rehype — с HAST (HTML AST). Обновления могут менять внутреннюю структуру этих деревьев. Это важно при использовании плагинов, которые напрямую изменяют узлы AST. Перед обновлением следует свериться с changelog библиотеки на предмет изменений в типах узлов, например:

    • heading.depth в Remark мог изменить допустимые значения.
    • В Rehype изменились имена некоторых атрибутов для элементов HTML.
  3. Плагины и их версии Большинство плагинов строго привязаны к версии Remark или Rehype. При обновлении ядра необходимо обновлять плагины до совместимых версий. Несовместимые версии могут привести к:

    • Невызову обработчика узлов.
    • Ошибкам при парсинге Markdown или HTML.
    • Нарушению порядка вызова плагинов.

Стратегия обновления

  1. Пошаговое обновление

    • Сначала обновляется unified до версии, совместимой с целевой версией Remark/Rehype.
    • Затем обновляются ядро Remark или Rehype.
    • В конце обновляются все плагины, проверяя changelog для каждого.
  2. Тестирование AST Для сложных проектов рекомендуется использовать snapshot-тесты AST перед и после обновления. Это позволяет обнаружить неожиданные изменения в структуре дерева. Пример проверки:

    import { unified } from 'unified';
    import remarkParse from 'remark-parse';
    import remarkStringify from 'remark-stringify';
    
    const processor = unified()
      .use(remarkParse)
      .use(remarkStringify);
    
    const tree = processor.parse('# Заголовок\n\nТекст');
    console.log(tree); // проверка структуры AST
  3. Проверка плагинов на deprecation Новые версии Remark/Rehype могут пометить старые методы или API как устаревшие. Важно проверять console.warn и документацию плагина на предмет deprecated-методов.

  4. Обновление TypeScript-типов Remark и Rehype имеют свои типы для AST и плагинов. После обновления библиотек нужно проверить типы: иногда изменяются имена полей или интерфейсы плагинов. Например, MDAST узел link.url может быть переименован в url.href в будущих версиях.


Практические советы

  • Заморозка зависимостей: перед обновлением фиксировать текущие версии через package-lock.json или pnpm-lock.yaml для возможности отката.
  • Изоляция тестовой среды: создается отдельная ветка или репозиторий для проверки обновлений на существующих документах.
  • Автоматизация тестирования: CI/CD с snapshot-тестами Markdown и HTML позволяет выявить расхождения в выводе после обновления.
  • Документация AST: всегда держать под рукой схемы MDAST и HAST, так как они помогают быстро адаптировать кастомные плагины под новую версию.

Типичные ошибки при обновлении

  1. Ошибка Plugin not found Возникает при несовместимости версии плагина с ядром Remark/Rehype. Решение: обновление или замена плагина.

  2. Неправильный рендер HTML/Markdown AST изменился, и плагины корректно не обрабатывают узлы. Решение: пересмотреть обход узлов и методы visit/map.

  3. TypeScript ошибки Из-за изменения интерфейсов узлов AST. Решение: обновление типов @types/remark-* или использование встроенных типов библиотек.


Вывод структуры обновления

  1. Обновление unified.
  2. Обновление ядра Remark/Rehype.
  3. Обновление всех плагинов.
  4. Проверка AST и snapshot-тесты.
  5. Исправление кастомных плагинов и типов.

Соблюдение этого порядка минимизирует риски ошибок и обеспечивает плавный переход на новые версии без потери функциональности.