Регистрация плагинов

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


Подключение плагинов

Для использования плагина необходимо сначала установить его через npm или подключить локально:

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

После подключения объект md становится готов к регистрации плагинов.


Метод use

Основной способ регистрации плагинов — метод use экземпляра Markdown-it. Сигнатура метода:

md.use(pluginFunction, ...options);
  • pluginFunction — функция-плагин, которая принимает экземпляр Markdown-it и опциональные параметры.
  • options — любые дополнительные аргументы, передаваемые плагину для конфигурации его поведения.

Пример базовой регистрации:

md.use(myPlugin, { option1: true, option2: 'value' });

Метод use поддерживает цепочку вызовов, что удобно при регистрации нескольких плагинов:

md
  .use(pluginA)
  .use(pluginB, { level: 2 })
  .use(pluginC);

Структура плагина

Функция-плагин обычно имеет следующий вид:

function myPlugin(md, options) {
    // Настройка правил блоков
    md.block.ruler.before('paragraph', 'my_block', function(state, startLine, endLine, silent) {
        // логика обработки блока
    }, { alt: [] });

    // Настройка правил инлайна
    md.inline.ruler.after('emphasis', 'my_inline', function(state, silent) {
        // логика обработки инлайнового элемента
    });

    // Настройка кастомного рендера
    md.renderer.rules.my_inline = function(tokens, idx, options, env, self) {
        return `<span class="my-inline">${tokens[idx].content}</span>`;
    };
}

Ключевые моменты структуры:

  • Блоковые правила (block.ruler) — позволяют добавлять новые блоки Markdown или модифицировать существующие (например, обработка нестандартных заголовков или специальных контейнеров).
  • Инлайновые правила (inline.ruler) — отвечают за обработку внутренних элементов текста: ссылки, эмфазис, специальные символы.
  • Рендеринг (renderer.rules) — определяет, как токены будут преобразованы в HTML или другой выходной формат.

Порядок применения плагинов

Плагины применяются в том порядке, в котором они зарегистрированы через use. Это важно, если один плагин зависит от результатов работы другого. Рекомендуется:

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

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

1. Плагин для подсветки специальных слов:

function highlightWords(md, words) {
    md.inline.ruler.push('highlight', function(state, silent) {
        const tokenText = state.src.slice(state.pos, state.pos + 20);
        for (let word of words) {
            if (tokenText.startsWith(word)) {
                const token = state.push('highlight', '', 0);
                token.content = word;
                state.pos += word.length;
                return true;
            }
        }
        return false;
    });

    md.renderer.rules.highlight = function(tokens, idx) {
        return `<mark>${tokens[idx].content}</mark>`;
    };
}

md.use(highlightWords, ['Markdown', 'плагин']);

2. Плагин для добавления нумерованных блоков:

function numberedBlock(md) {
    md.block.ruler.before('paragraph', 'numbered_block', function(state, startLine, endLine, silent) {
        const lineText = state.getLines(startLine, startLine + 1, state.blkIndent, false).trim();
        if (!lineText.startsWith('##')) return false;

        if (!silent) {
            const token = state.push('numbered_block', 'div', 0);
            token.attrs = [['class', 'numbered-block']];
            token.content = lineText.slice(2).trim();
        }

        state.line = startLine + 1;
        return true;
    });

    md.renderer.rules.numbered_block = function(tokens, idx) {
        return `<div class="numbered-block">${tokens[idx].content}</div>`;
    };
}

md.use(numberedBlock);

Встроенные хуки и фильтры

Markdown-it позволяет плагинам использовать дополнительные хуки:

  • core — обрабатывает все токены на уровне ядра.
  • postprocess — фильтрует или модифицирует токены перед рендерингом.
  • env — передача дополнительных данных между плагинами.

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

md.core.ruler.push('replace_emoji', function(state) {
    state.tokens.forEach(token => {
        if (token.type === 'inline') {
            token.children.forEach(child => {
                if (child.type === 'text') {
                    child.content = child.content.replace(/:smile:/g, '?');
                }
            });
        }
    });
});

Советы по разработке плагинов

  • Всегда проверять silent в правилах, чтобы корректно поддерживать парсинг без модификации состояния.
  • Использовать уникальные имена для токенов, чтобы избежать конфликтов с другими плагинами.
  • Разделять блоковые и инлайновые правила для ясной структуры.
  • Перед публикацией плагина тестировать на реальных Markdown-документах, учитывая различные комбинации заголовков, списков и таблиц.

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