Объект Ruler

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


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

Ruler представлен как объект с набором методов, обеспечивающих гибкое управление правилами:

1. push(name, fn, options)

Добавляет новое правило в конец списка для конкретного уровня парсинга.

  • name — уникальное имя правила (строка), используется для идентификации и последующих операций.
  • fn — функция-обработчик, принимающая параметры (state, startLine, endLine, silent).
  • options — объект с дополнительными настройками, такими как alt для указания альтернативных правил.

Пример использования:

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

md.block.ruler.push('my_rule', (state, startLine, endLine, silent) => {
  // Логика обработки блока
  return true; // возвращает true, если правило сработало
});

2. before(beforeName, name, fn, options)

Вставляет правило перед указанным именем beforeName.

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

Пример:

md.block.ruler.before('paragraph', 'my_rule_before', (state, startLine, endLine, silent) => {
  // Логика обработки перед параграфом
  return false;
});

3. after(afterName, name, fn, options)

Добавляет правило после указанного afterName.

  • Используется для расширения функционала без нарушения существующей последовательности.
  • Часто применяется для внедрения новых правил в цепочку обработки списков, заголовков и таблиц.

4. at(index, name, fn, options)

Вставляет правило в точное положение по индексу.

  • Позволяет полное управление порядком применения правил.
  • Удобно для оптимизации производительности при большом количестве пользовательских правил.

5. getRules()

Возвращает массив всех функций-правил для данного уровня.

  • Используется для анализа текущего состояния Ruler.
  • Можно динамически изменять поведение Markdown в процессе работы.

6. has(name)

Проверяет наличие правила с указанным именем.

if (!md.block.ruler.has('my_rule')) {
  md.block.ruler.push('my_rule', myRuleFunction);
}

7. enable(names) / disable(names)

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

  • Включение и отключение правил помогает создавать динамические конфигурации парсера.
  • Отключенные правила пропускаются при обработке текста.

Структура функций-правил

Функция-правило для block или inline уровня имеет следующий вид:

function myRule(state, startLine, endLine, silent) {
  // state — объект состояния парсера
  // startLine, endLine — границы текущей обрабатываемой строки
  // silent — режим проверки без генерации токенов
  return false; // true — если правило применилось
}

Объект state содержит ключевые свойства:

  • src — исходный текст Markdown.
  • tokens — массив токенов, формируемых правилом.
  • lines — массив строк текста.
  • bMarks, eMarks, tShift — массивы с информацией о границах строк и отступах.
  • level — текущий уровень вложенности блоков.

Примеры использования

Добавление кастомного блока

md.block.ruler.push('spoiler', (state, startLine, endLine, silent) => {
  const line = state.src.split('\n')[startLine];
  if (!line.startsWith(':::spoiler')) return false;

  if (!silent) {
    const token = state.push('spoiler_open', 'div', 1);
    token.attrPush(['class', 'spoiler']);
    state.push('inline', '', 0).content = line.slice(10).trim();
    state.push('spoiler_close', 'div', -1);
  }

  return true;
});

Переупорядочивание стандартных правил

// Перемещаем правило обработки заголовков выше правила параграфов
md.block.ruler.before('paragraph', 'heading', md.block.ruler.getRules()['heading']);

Взаимодействие с уровнями парсинга

Ruler существует для двух уровней:

  1. block — обработка структурных элементов: параграфы, заголовки, списки, блоки кода.
  2. inline — обработка внутренних элементов строки: ссылки, эмодзи, жирный текст, италик.

Каждый уровень имеет свой экземпляр Ruler с собственным набором правил. Например:

md.block.ruler.push('custom_block', customBlockFn);
md.inline.ruler.push('custom_emphasis', customEmphasisFn);

Продвинутое управление правилами

  • Удаление правил: с помощью ruler.enable([]) и ruler.disable([]) можно временно блокировать правила.
  • Композиция правил: создание цепочек обработчиков для сложных Markdown-структур.
  • Альтернативные правила: использование опции alt при добавлении правила позволяет указать альтернативы для конфликтующих стандартных правил.

Ключевые моменты

  • Ruler управляет порядком выполнения правил Markdown-it.
  • Каждое правило имеет уникальное имя и функцию обработки.
  • Позволяет добавлять, удалять, перемещать и временно отключать правила.
  • Поддерживает работу на уровнях block и inline.
  • Основной инструмент для расширения Markdown и создания пользовательских плагинов.

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