Объект Renderer

Объект Renderer в библиотеке Markdown-it является центральным компонентом, отвечающим за преобразование токенов, сгенерированных парсером Markdown, в итоговый HTML. Он представляет собой набор методов, которые соответствуют различным типам токенов. Понимание его структуры и возможностей позволяет гибко кастомизировать вывод и внедрять собственные правила рендеринга.


Структура объекта Renderer

Renderer — это класс с ключевым методом renderToken, который отвечает за рендеринг каждого отдельного токена. Его основная задача — преобразовать токен в строку HTML, учитывая его тип, вложенность и атрибуты.

Основные свойства и методы:

  • rules — объект, где ключами являются типы токенов, а значениями — функции рендеринга.
  • render — метод, который принимает массив токенов и возвращает готовый HTML.
  • renderInline — метод для рендеринга токенов inline-уровня, таких как текст, ссылки и эмоджи.
  • renderToken — базовый метод, который используется внутри render, обеспечивает корректное открытие и закрытие тегов.

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

const md = require('markdown-it')();
console.log(md.renderer.rules);

Результатом будет объект с предопределёнными функциями рендеринга для стандартных токенов, таких как paragraph_open, paragraph_close, link_open и других.


Функции рендеринга

Каждая функция рендеринга имеет стандартную сигнатуру:

function(tokens, idx, options, env, self) {
  return string; // возвращает HTML
}

Где:

  • tokens — массив всех токенов документа.
  • idx — индекс текущего токена в массиве.
  • options — объект с опциями Markdown-it.
  • env — объект окружения, который может содержать дополнительные данные для кастомизации рендеринга.
  • self — ссылка на рендерер, используется для рекурсивного вызова метода renderToken.

Пример функции рендеринга параграфа:

md.renderer.rules.paragraph_open = function(tokens, idx) {
  return '<p class="custom-paragraph">';
};

md.renderer.rules.paragraph_close = function(tokens, idx) {
  return '</p>\n';
};

Пользовательские правила рендеринга

Одним из мощнейших инструментов Renderer является возможность добавления или замены правил для любых токенов. Это позволяет, например, внедрять CSS-классы, изменять структуру HTML или добавлять собственные элементы.

Пример рендеринга ссылок с атрибутом target="_blank":

md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
  const token = tokens[idx];
  const hrefIndex = token.attrIndex('href');

  if (hrefIndex >= 0) {
    token.attrPush(['target', '_blank']);
  }

  return self.renderToken(tokens, idx, options);
};

В этом примере используется self.renderToken, чтобы сохранить стандартное поведение рендеринга, дополняя его кастомными атрибутами.


Рендеринг inline-токенов

Inline-токены (например, текст, эмоджи, ссылки внутри параграфов) обрабатываются с помощью метода renderInline. Это важно для генерации HTML внутри элементов, не требующих отдельного блока.

Пример рендеринга текста с преобразованием всех букв в верхний регистр:

md.renderer.rules.text = function(tokens, idx) {
  return tokens[idx].content.toUpperCase();
};

Метод renderInline автоматически вызывает функции рендеринга для всех inline-токенов внутри контейнера, поэтому достаточно изменить правило для text, чтобы трансформация применилась ко всему документу.


Взаимодействие с токенами и атрибутами

Каждый токен представляет собой объект с ключевыми свойствами:

  • type — тип токена (например, paragraph_open, heading_open, fence).
  • tag — HTML-тег, связанный с токеном.
  • attrs — массив атрибутов [имя, значение].
  • content — текстовое содержимое (для inline-токенов).
  • children — массив вложенных токенов (для inline-структур).
  • nesting — уровень вложенности: 1 — открывающий тег, -1 — закрывающий, 0 — одиночный токен.

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


Использование env для контекстного рендеринга

Объект env передается в функции рендеринга и может использоваться для хранения состояния между токенами. Например, можно хранить текущий раздел документа, идентификаторы, счетчики или любые дополнительные данные, которые нужны для кастомного HTML.

Пример:

md.renderer.rules.heading_open = function(tokens, idx, options, env) {
  const level = tokens[idx].tag.slice(1);
  env.headingCount = (env.headingCount || 0) + 1;
  return `<${tokens[idx].tag} id="heading-${env.headingCount}">`;
};

Каждый заголовок получает уникальный идентификатор на основе счётчика в env.


Подытоживая возможности

  • Полный контроль над HTML-выводом через методы rules и renderToken.
  • Поддержка кастомных атрибутов и стилей для любых токенов.
  • Обработка inline-токенов с помощью renderInline.
  • Контекстный рендеринг через объект env.
  • Возможность рекурсивного вызова стандартного рендеринга для комбинирования кастомного и базового HTML.

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