Добавление рендер-функций

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

npm install markdown-it

или

yarn add markdown-it

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

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

Этот объект md обеспечивает функции парсинга Markdown в HTML. Основной метод — render, который принимает строку с Markdown и возвращает HTML:

const result = md.render('# Заголовок\n\nТекст абзаца');
console.log(result);

Выведет:

<h1>Заголовок</h1>
<p>Текст абзаца</p>

Добавление пользовательских рендер-функций

Markdown-it использует систему токенов, каждый элемент Markdown при разборе преобразуется в токен с типом, например: paragraph_open, inline, link_open и т.д. Рендер-функции определяют, как токен превращается в HTML.

Рендер-функции можно добавлять через объект renderer.rules. Стандартный синтаксис:

md.renderer.rules['имя_токена'] = function (tokens, idx, options, env, self) {
    // tokens — массив всех токенов
    // idx — индекс текущего токена
    // options — опции Markdown-it
    // env — объект окружения для передачи данных между рендером и парсером
    // self — ссылка на рендерер по умолчанию
    return 'ваш HTML';
};

Пример: кастомное оформление заголовков

Пусть необходимо добавить к каждому заголовку класс CSS custom-heading:

md.renderer.rules.heading_open = function (tokens, idx, options, env, self) {
    const token = tokens[idx];
    token.attrPush(['class', 'custom-heading']); // добавляем атрибут class
    return self.renderToken(tokens, idx, options); // рендерим токен стандартным образом
};

const result = md.render('# Пример заголовка');
console.log(result);

Результат:

<h1 class="custom-heading">Пример заголовка</h1>

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

Чтобы изменять ссылки, используется токен link_open. Например, можно добавлять target="_blank" ко всем ссылкам:

md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
    const token = tokens[idx];
    token.attrSet('target', '_blank'); // добавляем target="_blank"
    return self.renderToken(tokens, idx, options);
};

const result = md.render('[Ссылка](https://example.com)');
console.log(result);

Выведет:

<a href="https://example.com" target="_blank">Ссылка</a>

Кастомный рендер для отдельных маркеров

Markdown-it позволяет создавать новые токены и рендерить их особым образом. Например, создание пользовательского блока «warning»:

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

function warningPlugin(md) {
    md.block.ruler.before('paragraph', 'warning', function(state, startLine, endLine, silent) {
        const lineText = state.getLines(startLine, endLine, 0, true);
        if (!lineText.startsWith('!!! warning')) return false;

        if (silent) return true;

        const token = state.push('warning_open', 'div', 1);
        token.block = true;
        token.attrs = [['class', 'warning-block']];

        const contentToken = state.push('inline', '', 0);
        contentToken.content = lineText.replace('!!! warning', '').trim();
        contentToken.children = [];

        state.push('warning_close', 'div', -1);
        state.line = startLine + 1;
        return true;
    });

    md.renderer.rules.warning_open = function(tokens, idx) {
        return '<div class="warning-block">\n';
    };
    md.renderer.rules.warning_close = function(tokens, idx) {
        return '</div>\n';
    };
}

md.use(warningPlugin);

const result = md.render('!!! warning Это важное предупреждение!');
console.log(result);

Результат:

<div class="warning-block">
Это важное предупреждение!
</div>

Использование self.renderToken и сохранение стандартного рендеринга

При переопределении рендер-функции важно сохранять возможность стандартного рендеринга. Для этого применяется self.renderToken:

md.renderer.rules.strong_open = function(tokens, idx, options, env, self) {
    tokens[idx].attrJoin('class', 'highlight'); // добавляем класс
    return self.renderToken(tokens, idx, options);
};

Такой подход комбинирует кастомное оформление с полной совместимостью стандартного Markdown.

Работа с токенами inline

Inline-токены содержат текст и вложенные элементы. Для их обработки используется вложенный массив children:

md.renderer.rules.em_open = function(tokens, idx, options, env, self) {
    tokens[idx].attrJoin('style', 'font-style: italic; color: red;');
    return self.renderToken(tokens, idx, options);
};

const result = md.render('Это *важно*!');
console.log(result);

Результат:

<p>Это <em style="font-style: italic; color: red;">важно</em>!</p>

Передача данных через env

Объект env позволяет передавать дополнительные данные в рендер-функции. Например, для подсчета количества ссылок:

const env = { linkCount: 0 };

md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
    env.linkCount = (env.linkCount || 0) + 1;
    return self.renderToken(tokens, idx, options);
};

md.render('[Google](https://google.com)\n[Example](https://example.com)', env);
console.log(env.linkCount); // 2

Итоговые рекомендации по рендер-функциям

  • Использовать renderer.rules['token_name'] для переопределения стандартного рендера.
  • Для сохранения стандартного поведения применять self.renderToken.
  • Для новых токенов создавать плагин с block.ruler или inline.ruler.
  • Передавать состояние через env для гибкой логики.
  • Для inline-токенов работать с children, чтобы изменять вложенные элементы.

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