Приоритет и порядок выполнения

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

Структура обработки

Markdown-it разделяет обработку текста на два уровня:

  1. Block-level – блочные элементы (параграфы, заголовки, списки, блоки кода, цитаты).
  2. Inline-level – внутристрочные элементы (ссылки, выделение, эмоджи, коды).

Каждый уровень использует систему токенов: текст преобразуется в последовательность токенов, которые затем рендерятся в HTML. Понимание последовательности генерации токенов помогает управлять приоритетом правил.

Система правил и их порядок

Правила в Markdown-it определяются как функции, выполняющие определённое преобразование текста в токены. Они делятся на три основных типа:

  • Core rules – базовая обработка текста: разбиение на блоки, управление пустыми строками, обработка ссылок.
  • Block rules – обработка блочных элементов, выполняется последовательно сверху вниз по списку правил.
  • Inline rules – обрабатывают содержимое блоков, применяются к каждому блочному токену, содержащему текст.

Порядок выполнения блоков важен: Markdown-it проходит список правил, и первый совпавший паттерн запускается до следующих. Это позволяет отменять стандартное поведение, добавляя кастомные правила с нужным приоритетом.

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

Каждое правило имеет определённую позицию в массиве parser.rules. Для управления приоритетом можно использовать методы:

  • ruler.before(name, newRuleName, ruleFunc) – добавляет правило перед существующим.
  • ruler.after(name, newRuleName, ruleFunc) – добавляет правило после указанного.
  • ruler.push(newRuleName, ruleFunc) – добавляет правило в конец цепочки.

Пример:

const md = require('markdown-it')();

md.inline.ruler.before('emphasis', 'custom_bold', function(state, silent) {
  // логика собственного правила
  return false;
});

В этом примере правило custom_bold будет применяться перед стандартным обработчиком выделения текста.

Core rules и их влияние на блоки

Core rules обрабатываются до всех block и inline правил. Ключевые моменты:

  • normalize – преобразует строки в стандартный формат.
  • block – отвечает за разбиение на блоки и установку типа токена.
  • inline – запускает inline-парсер на содержимом блочного токена.

Именно последовательность этих правил обеспечивает правильное распознавание вложенных элементов. Изменение порядка core rules может нарушить обработку Markdown.

Inline rules и конфликт токенов

Inline rules используют стек и позицию курсора для поиска совпадений. Конфликты происходят, если несколько правил совпадают на одном участке текста. Markdown-it решает их по позиции в массиве правил, поэтому:

  • более специфические правила добавляют перед стандартными;
  • правила с меньшей приоритетностью оставляют текст для стандартных парсеров.

Примеры практических конфигураций

  1. Игнорирование определённых символов
md.inline.ruler.before('emphasis', 'ignore_dollar', function(state, silent) {
  let pos = state.pos;
  if (state.src[pos] === '$') {
    state.pos += 1;
    return true;
  }
  return false;
});
  1. Создание собственного синтаксиса ссылок
md.inline.ruler.after('link', 'custom_link', function(state, silent) {
  const pos = state.pos;
  // логика поиска и генерации токена custom_link
  return false;
});
  1. Перенастройка блочных правил
md.block.ruler.before('paragraph', 'custom_block', function(state, startLine, endLine, silent) {
  const lineText = state.getLines(startLine, startLine + 1, 0, false);
  if (lineText.startsWith('%%')) {
    if (!silent) {
      const token = state.push('custom_block', 'div', 0);
      token.content = lineText.slice(2).trim();
    }
    return true;
  }
  return false;
});

Влияние на производительность

Порядок выполнения правил напрямую влияет на производительность:

  • Частые проверки должны идти после редких или сложных.
  • Простые и легкие правила можно ставить перед тяжелыми, чтобы избежать лишнего обхода текста.
  • Для inline-правил критично минимизировать перемещение курсора и повторные проверки символов.

Логика токенов и рендеринг

После генерации токенов Markdown-it строит дерево рендеринга. Токены хранят поля:

  • type – тип элемента (paragraph_open, strong_open, text).
  • tag – HTML-тег для рендера.
  • children – вложенные токены для inline-обработки.
  • level – глубина вложенности, определяет правильное закрытие блоков.

Понимание этих полей позволяет тонко управлять порядком вставки токенов и их рендерингом.