Создание плагинов

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


Пользовательские рендереры

Рендерер отвечает за преобразование токенов Markdown в HTML. В Marked можно создать собственный рендерер, наследуя стандартный, или полностью переопределяя методы.

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

import { marked } from 'marked';

class CustomRenderer extends marked.Renderer {
  heading(text, level, raw, slugger) {
    return `${text}`;
  }

  link(href, title, text) {
    return `${text}`;
  }
}

marked.use({ renderer: new CustomRenderer() });

const html = marked('# Заголовок');

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

  • Методы рендерера соответствуют типам токенов: heading, link, paragraph, code, list и другие.
  • Каждый метод получает текстовое содержимое и дополнительные параметры, позволяя модифицировать результат.
  • Рендерер можно использовать совместно с опциями Marked через marked.use({ renderer }).

Интеграция с лексером и токенами

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

Пример добавления нового токена:

import { marked } from 'marked';

const highlightToken = {
  name: 'highlight',
  level: 'inline',
  start(src) { return src.indexOf('=='); },
  tokenizer(src, tokens) {
    const match = /^==(.+?)==/.exec(src);
    if (match) {
      return { type: 'highlight', raw: match[0], text: match[1] };
    }
  },
  renderer(token) {
    return `${token.text}`;
  }
};

marked.use({ extensions: [highlightToken] });

const html = marked('Это ==важное== слово.');

Особенности работы с токенами:

  • name — уникальное имя токена.
  • level — указывает, относится ли токен к блочному (block) или встроенному (inline) содержимому.
  • start — функция, ускоряющая поиск возможного токена.
  • tokenizer — основная функция, создающая токен.
  • renderer — функция для отображения токена в HTML.

Расширение функциональности через плагины

Плагины позволяют:

  1. Добавлять новые токены и синтаксис.
  2. Модифицировать существующие методы рендерера.
  3. Менять процесс парсинга Markdown на любом этапе.

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

import { marked } from 'marked';

const quotePlugin = {
  extensions: [{
    name: 'customQuote',
    level: 'block',
    start(src) { return src.indexOf('>>>'); },
    tokenizer(src) {
      const match = /^>>>([\s\S]+?)\n{2,}/.exec(src);
      if (match) {
        return { type: 'customQuote', raw: match[0], text: match[1].trim() };
      }
    },
    renderer(token) {
      return `
${token.text}
`; } }] }; marked.use(quotePlugin); const html = marked('>>> Это цитата с кастомным оформлением\n\nСледующий абзац');
  • Плагины могут содержать массив extensions, где каждый элемент описывает отдельное расширение.
  • Метод renderer можно полностью настроить для HTML, React или других целей.
  • Поддерживается множественное подключение плагинов, при этом они обрабатываются в порядке добавления.

События и хук-подход

Для более гибкой интеграции Marked позволяет использовать хуки. Хук — это функция, которая вызывается на определенном этапе обработки Markdown.

Примеры хуков:

  • walkTokens(token): вызывается для каждого токена перед рендерингом.
  • renderer.hook(type, callback): позволяет изменить поведение определенного метода рендерера.

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

marked.use({
  walkTokens(token) {
    if (token.type === 'link') {
      token.href = token.href.startsWith('http') ? token.href : `https://${token.href}`;
    }
  }
});

const html = marked('[Google](www.google.com)');

Хуки обеспечивают:

  • Централизованную обработку токенов.
  • Возможность логирования или анализа Markdown.
  • Изменение структуры токенов без прямой модификации рендерера.

Советы по созданию производительных плагинов

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