Структура парсера

Markdown-it — это высокопроизводительная библиотека для парсинга Markdown в JavaScript, реализующая строгую и расширяемую архитектуру парсера. Базовая структура строится вокруг двух основных этапов: лексического анализа (tokenization) и синтаксического анализа (parsing), каждый из которых играет ключевую роль в преобразовании текста Markdown в HTML.

Лексический анализ

На первом этапе исходный текст Markdown преобразуется в поток токенов. Каждый токен — это объект с определёнными свойствами:

  • type — тип токена, например, paragraph_open, heading_close, inline.
  • tag — HTML-тег, который соответствует данному токену.
  • attrs — массив атрибутов, применяемых к тегу, в формате [ключ, значение].
  • map — диапазон строк исходного текста, охватываемый токеном.
  • nesting — уровень вложенности; 1 для открытия тега, -1 для закрытия, 0 для одиночного токена.
  • content — текстовое содержимое для токенов типа inline.

Лексический анализ производится с помощью цепочки правил блоков (block rules) и правил inline (inline rules). Блоковые правила определяют структуру документа, такие как заголовки, списки и блоки кода, а inline-правила обрабатывают подчёркивания, ссылки, эмодзи и форматирование текста внутри строки.

Правила блоков

Markdown-it использует массив функций block rules, которые последовательно проверяют текст на совпадение с определёнными конструкциями. Примеры основных правил:

  • heading — определяет заголовки через # или ===.
  • paragraph — создаёт параграфы для обычного текста.
  • blockquote — формирует блоки цитат с >.
  • fence — обрабатывает блоки кода с тройными апострофами.
  • list — распознаёт маркированные и нумерованные списки.

Каждое правило получает текущий индекс строки и весь массив строк, проверяет соответствие, создаёт токены и возвращает количество обработанных строк. Если правило не срабатывает, управление передаётся следующему правилу в цепочке.

Inline-анализ

Inline-токены создаются для обработки текста внутри блоков. Inline-parser выполняет следующие шаги:

  1. Разделяет строку на сегменты текста и спецсимволы.

  2. Применяет правила inline, например:

    • emphasis — выделение курсивом и жирным.
    • link — создание ссылок и изображений.
    • code — выделение inline-кода.
  3. Генерирует токены text, strong_open, em_open и другие, которые будут встроены в блок-токены.

Inline-токены всегда вложены в родительский блок-токен типа inline, что обеспечивает корректную структуру HTML при рендеринге.

Структура токенов и вложенность

Токены в Markdown-it имеют иерархическую структуру, которая позволяет:

  • Управлять вложенными списками, таблицами и блоками.
  • Легко модифицировать отдельные элементы через плагины.
  • Поддерживать точное соответствие Markdown-синтаксиса HTML-структуре.

Пример структуры:

[
  { "type": "paragraph_open", "tag": "p", "nesting": 1 },
  { "type": "inline", "content": "Пример текста", "children": [
      { "type": "text", "content": "Пример текста" }
    ]
  },
  { "type": "paragraph_close", "tag": "p", "nesting": -1 }
]

Рендеринг HTML

После формирования токенов Markdown-it передаёт их рендереру, который преобразует каждый токен в HTML:

  • Метод renderer.render(tokens, options, env) обходят массив токенов.
  • Для каждого токена вызывается соответствующая функция рендерера, определяющая конечный HTML.
  • Поддерживаются кастомные рендереры, позволяющие изменять вывод без изменения логики парсера.

Плагины и расширяемость

Архитектура Markdown-it построена так, чтобы расширять функциональность через плагины:

  • Добавление новых правил блоков и inline-правил.
  • Модификация существующих рендереров.
  • Интерцептирование токенов перед рендерингом для вставки кастомного HTML.

Подключение плагина выглядит как вызов md.use(plugin, options), где plugin получает экземпляр Markdown-it и добавляет новые правила или модифицирует существующие.

Итоговая структура парсера

В итоге, парсер Markdown-it состоит из трёх ключевых компонентов:

  1. Лексический анализатор блоков — создание базовых структур документа.
  2. Inline-анализатор — детальная обработка содержимого блоков.
  3. Рендерер HTML — преобразование токенов в HTML с возможностью расширений через плагины.

Эта модульная архитектура делает Markdown-it мощным инструментом для работы с Markdown в веб-приложениях и Node.js, обеспечивая баланс между скоростью, гибкостью и точностью преобразования.