Философия синтаксических деревьев

Синтаксическое дерево (AST, Abstract Syntax Tree) в экосистеме JavaScript — это структурированное представление документа, где каждый элемент текста, разметки или кода превращается в узел дерева с определённым типом и свойствами. Remark и Rehype строят такие деревья для Markdown и HTML соответственно, превращая документ в объект, с которым можно безопасно и эффективно работать программно.

Основные принципы работы с AST

  • Иерархичность: Узлы образуют древовидную структуру, где родительские узлы содержат дочерние. Это позволяет отражать логическую вложенность документа — параграфы, списки, заголовки, таблицы.
  • Типизация узлов: Каждый узел имеет свой тип (heading, paragraph, text, link для Remark; element, text, comment для Rehype), который определяет его роль и допустимые свойства.
  • Атрибуты и данные: Узлы могут хранить данные о содержимом, например, текст для text, уровни заголовка для heading, URL для link. Дополнительно можно хранить метаданные через поля data или position.

Принцип единой обработки контента

Remark и Rehype следуют философии одинакового обращения с контентом: вне зависимости от исходного формата, документ преобразуется в дерево с однородной структурой. Это даёт возможность:

  • Писать универсальные плагины для анализа и модификации узлов.
  • Легко конвертировать Markdown в HTML и обратно.
  • Обрабатывать контент без прямого парсинга строки за строкой.

Разделение ответственности

  • Remark работает с Markdown и его синтаксисом, формируя AST типа mdast (Markdown Abstract Syntax Tree).
  • Rehype работает с HTML, формируя AST типа hast (HTML Abstract Syntax Tree).

Это разделение позволяет оптимизировать работу с каждым форматом, сохраняя концепцию единого дерева. Для трансформации между Markdown и HTML используют промежуточное представление и последовательность плагинов.

Работа с узлами и плагинами

Узлы AST можно:

  • Читать: анализировать структуру документа, извлекать текст, ссылки, заголовки.
  • Модифицировать: добавлять, удалять или изменять узлы.
  • Создавать новые узлы: формировать динамический контент программно.

Плагины Remark и Rehype работают через посещения узлов. Типичная структура плагина:

function plugin() {
  return (tree) => {
    visit(tree, 'type', (node) => {
      // логика обработки узла
    });
  };
}

Где visit рекурсивно проходит по дереву, находя узлы определённого типа, и выполняет заданные действия.

Концепция неизменяемости и композиции

В экосистеме часто применяется подход чистой трансформации: дерево не изменяется напрямую, а создаётся его новая версия с нужными изменениями. Это позволяет:

  • Сохранять исходный документ для отката.
  • Комбинировать несколько плагинов без конфликтов.
  • Обеспечивать предсказуемое поведение обработки.

Использование AST для анализа и визуализации

AST позволяет строить сложные инструменты:

  • Генераторы оглавлений по структуре заголовков.
  • Проверку семантической корректности Markdown или HTML.
  • Подсветку ссылок, кода и других элементов.
  • Конвертацию Markdown в PDF или презентации через промежуточное представление.

Принципы архитектуры Remark/Rehype

  1. Модульность: дерево обрабатывается по шагам, каждый плагин выполняет отдельную функцию.
  2. Прозрачность: дерево можно вывести в консоль или сериализовать, чтобы понять, что произошло на каждом этапе.
  3. Совместимость: структуры AST строго стандартизированы, что упрощает совместное использование библиотек и плагинов.

Пример узла Markdown AST

{
  "type": "heading",
  "depth": 2,
  "children": [
    {
      "type": "text",
      "value": "Философия синтаксических деревьев"
    }
  ]
}
  • type: "heading" — тип узла.
  • depth: 2 — уровень заголовка.
  • children — массив вложенных узлов, в данном случае текстовый узел.

Преобразование Markdown → HTML

Pipeline обычно выглядит так:

  1. Remark парсит Markdown → mdast.
  2. Плагины модифицируют mdast.
  3. mdast преобразуется в hast с помощью remark-rehype.
  4. Rehype применяет плагины → модифицирует hast.
  5. Rehype сериализует hast в HTML.

Это последовательное использование AST разных уровней позволяет гибко управлять контентом на всех стадиях.


Хотя деревья AST могут показаться сложными, их философия строится на трёх ключевых принципах: структура, однородность и модульность. Понимание этих принципов открывает возможности для глубокого анализа, трансформации и генерации контента в JavaScript.