Концепция правил

Markdown-it строится на концепции правил (rules), которые определяют, как исходный текст Markdown преобразуется в HTML. Каждый тип синтаксиса — заголовки, списки, ссылки, цитаты, кодовые блоки — имеет свой набор правил, реализованных через парсеры блоков (block parsers) и парсеры инлайнов (inline parsers). Эти правила позволяют гибко настраивать поведение парсинга и расширять стандартный Markdown.


Структура правил

Правила в Markdown-it организованы в цепочки обработки, которые последовательно вызываются движком. Основные виды правил:

  1. Block Rules — работают на уровне блоков текста, например, распознают заголовки, списки, абзацы, кодовые блоки.
  2. Inline Rules — применяются внутри блоков, отвечают за обработку ссылок, выделений, изображений и других элементов.

Каждое правило представляет собой функцию с определённой сигнатурой:

function ruleFunction(state, startLine, endLine, silent) {
  // state — объект состояния парсера
  // startLine, endLine — границы обрабатываемого блока
  // silent — флаг проверки без изменения состояния
}
  • state хранит исходный текст и текущее состояние синтаксического дерева.
  • silent используется для проверки, подходит ли фрагмент под правило, без фактической генерации токенов.

Функция должна возвращать true, если правило применено, и false, если нет.


Токены и их назначение

Правила создают токены, которые представляют элементы Markdown. Каждый токен имеет ключевые свойства:

  • type — тип токена (paragraph_open, heading_close, inline и т. д.).
  • tag — соответствующий HTML-тег (p, h1, ul, li).
  • content — текстовое содержимое (для inline-токенов).
  • attrs — массив атрибутов для HTML-элемента.
  • children — массив дочерних токенов для вложенной структуры.

Пример создания токена:

const token = state.push('paragraph_open', 'p', 1);
token.attrs = [['class', 'custom-paragraph']];

Настройка цепочки правил

Markdown-it хранит правила в цепочках, которые можно изменять через методы:

  • md.block.ruler — управляет блоковыми правилами.
  • md.inline.ruler — управляет инлайновыми правилами.

Методы для работы с правилами:

  • before(name, ruleName, ruleFunction) — вставляет новое правило перед существующим.
  • after(name, ruleName, ruleFunction) — вставляет новое правило после существующего.
  • push(ruleName, ruleFunction) — добавляет правило в конец цепочки.
  • enable(ruleName) / disable(ruleName) — включает или отключает правило.

Пример вставки собственного правила:

md.inline.ruler.before('emphasis', 'highlight', function(state, silent) {
  const pos = state.pos;
  if (state.src[pos] !== '^') return false;

  if (!silent) {
    const token = state.push('highlight_open', 'mark', 1);
    token.markup = '^';
    state.push('text', '', 0).content = 'выделенный текст';
    state.push('highlight_close', 'mark', -1);
  }

  state.pos += 2;
  return true;
});

Порядок обработки и приоритет

Порядок правил критически важен: Markdown-it вызывает их последовательно, и первое подходящее правило «захватывает» фрагмент текста. Блоковые правила обрабатываются до инлайновых, а внутри блоковых цепочек правила можно вставлять в любом месте, чтобы изменить приоритет.

Примеры стандартных блоковых правил:

  • code — кодовые блоки.
  • fence — многострочные блоки с языковой подсветкой.
  • blockquote — цитаты.
  • list — маркированные и нумерованные списки.

Инлайновые правила включают:

  • emphasisкурсив и жирный.
  • link — ссылки и изображения.
  • autolink — автоматическое преобразование URL в ссылки.

Расширяемость через правила

Markdown-it поддерживает подключение плагинов, которые добавляют новые правила или модифицируют существующие. Плагин получает объект md и может управлять цепочками правил:

function customPlugin(md) {
  md.inline.ruler.after('link', 'custom', function(state) {
    // новая обработка текста
  });
}
md.use(customPlugin);

Это позволяет реализовать:

  • Поддержку нестандартных синтаксисов (spoiler, highlight, footnote).
  • Добавление кастомных атрибутов и классов к HTML-элементам.
  • Модификацию стандартного поведения Markdown без изменения исходного кода библиотеки.

Практика работы с правилами

  1. Определить, какой тип правила требуется (блок или inline).
  2. Написать функцию с проверкой и созданием токенов.
  3. Вставить правило в цепочку в нужной позиции.
  4. Проверить корректность работы через флаг silent.
  5. Настроить последовательность вызовов, чтобы избежать конфликтов с другими правилами.

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