Типы контентных узлов

В экосистеме Remark и Rehype основой обработки Markdown и HTML являются деревья AST (Abstract Syntax Tree), где каждый элемент представлен узлом. Разделение узлов по типам позволяет точно управлять структурой документа и выполнять трансформации контента на различных уровнях. Понимание типов узлов критично для эффективного использования плагинов и написания собственных обработчиков.


1. Узлы Markdown в Remark

Remark оперирует деревом, называемым MDAST (Markdown Abstract Syntax Tree). Основные категории узлов:

  • Документные узлы (root)

    • Представляют весь документ Markdown.

    • Содержат в себе массив дочерних узлов (children), которые могут быть параграфами, заголовками, списками и так далее.

    • Пример:

      {
        type: 'root',
        children: [/* параграфы, заголовки, списки */]
      }
  • Блочные узлы (block)

    • Определяют структурные элементы документа:

      • paragraph — параграф текста.
      • heading — заголовок, с уровнем (depth) от 1 до 6.
      • blockquote — блок цитаты.
      • list — список, с параметрами ordered и start.
      • listItem — элемент списка.
      • thematicBreak — горизонтальная линия.
    • Пример узла заголовка:

      {
        type: 'heading',
        depth: 2,
        children: [
          { type: 'text', value: 'Подзаголовок' }
        ]
      }
  • Инлайновые узлы (inline)

    • Содержимое внутри блочных узлов:

      • text — простой текст.
      • emphasis — выделение курсивом.
      • strong — жирное выделение.
      • inlineCode — встроенный код.
      • link — ссылка, с атрибутами url и title.
      • image — изображение.
    • Пример узла ссылки:

      {
        type: 'link',
        url: 'https://example.com',
        title: 'Пример',
        children: [{ type: 'text', value: 'Перейти на сайт' }]
      }
  • Дополнительные узлы

    • code — блочный код, с языком (lang) и текстом (value).
    • html — произвольный HTML-контент.
    • definition и footnote — для ссылок и сносок.

2. Узлы HTML в Rehype

Rehype работает с HAST (HTML Abstract Syntax Tree), где узлы представляют элементы HTML. Основные типы узлов:

  • Элементные узлы (element)

    • Соответствуют тегам HTML.

    • Атрибуты хранятся в объекте properties.

    • Дочерние узлы находятся в массиве children.

    • Пример узла:

      {
        type: 'element',
        tagName: 'p',
        properties: {},
        children: [
          { type: 'text', value: 'Текст параграфа' }
        ]
      }
  • Текстовые узлы (text)

    • Содержат текстовое содержимое элементов.

    • Не имеют дочерних узлов.

    • Пример:

      { type: 'text', value: 'Простой текст' }
  • Комментарий (comment)

    • Содержит комментарий HTML.

    • Пример:

      { type: 'comment', value: 'Это комментарий' }
  • Документные узлы

    • root — корневой узел, аналогичный Remark.
    • doctype — для указания типа документа.
  • Прочие узлы

    • raw — сырые HTML-фрагменты.
    • element с атрибутом data используется для расширений и кастомных плагинов.

3. Связь узлов Remark и Rehype

Для конвертации Markdown в HTML часто используют цепочку: remark → rehype → stringify. В этом процессе:

  • MDAST трансформируется в HAST, при этом каждый блочный и инлайновый узел получает HTML-аналог.

    • paragraphp
    • headingh1-h6
    • strongstrong
    • emphasisem
  • Понимание типов узлов важно при написании плагинов, например:

    • Замена всех ссылок link на кастомные компоненты.
    • Добавление классов к заголовкам.
    • Преобразование кода с подсветкой синтаксиса.

4. Особенности работы с узлами

  • Каждый узел имеет обязательное свойство type.

  • Узлы могут содержать массив children или строку value, в зависимости от типа.

  • Разделение на блочные и инлайновые позволяет рекурсивно обходить дерево, не нарушая структуры.

  • Некоторые узлы имеют дополнительные свойства, специфичные для конкретного типа, например:

    • depth у заголовка.
    • lang у кода.
    • url и title у ссылок.
    • ordered и start у списков.
  • Для безопасной работы с деревом используются методы обхода, такие как unist-util-visit, которые позволяют выбирать узлы по типу и производить трансформации.


5. Практическое использование типов узлов

  • Фильтрация текста:

    import { visit } from 'unist-util-visit';
    visit(tree, 'text', node => {
      node.value = node.value.replace(/example/g, 'пример');
    });
  • Добавление CSS-классов к элементам:

    visit(tree, 'element', node => {
      if (node.tagName === 'h2') {
        node.properties.className = ['section-title'];
      }
    });
  • Генерация оглавления на основе узлов heading с уровнем depth:

    const toc = [];
    visit(tree, 'heading', node => {
      toc.push({ depth: node.depth, title: node.children[0].value });
    });

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