Обработка опций плагина

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

Передача опций при подключении плагина

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

const MarkdownIt = require('markdown-it');
const markdownItContainer = require('markdown-it-container');

const md = new MarkdownIt();

md.use(markdownItContainer, 'info', {
  render: function(tokens, idx) {
    if (tokens[idx].nesting === 1) {
      return '<div class="info">';
    } else {
      return '</div>';
    }
  }
});

Здесь третьим аргументом передаётся объект опций. Внутри плагина эти опции используются для изменения поведения парсера или генератора HTML. Важно помнить, что опции должны быть детерминированными и иметь значения по умолчанию, чтобы плагин оставался предсказуемым.

Типичные параметры плагинов

  • validate — функция проверки синтаксиса пользовательских блоков или маркеров. Обычно возвращает true, если токен соответствует ожидаемому формату.
  • render — функция генерации HTML. Получает массив токенов и индекс текущего токена. Позволяет полностью контролировать результат.
  • marker — символ, используемый для обозначения начала блока. Например, ::: для контейнеров.
  • level — указывает уровень вложенности токена относительно других блоков.

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

md.use(markdownItContainer, 'warning', {
  validate: function(params) {
    return params.trim().match(/^warning\s+/);
  },
  render: function(tokens, idx) {
    if (tokens[idx].nesting === 1) {
      return '<div class="warning">';
    } else {
      return '</div>';
    }
  }
});

Обработка опций с умолчаниями

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

function myPlugin(md, options = {}) {
  const defaultOptions = {
    marker: ':::',
    className: 'custom-block',
    renderContent: content => content
  };

  const opts = Object.assign({}, defaultOptions, options);

  md.block.ruler.before('fence', 'custom_block', function(state, startLine, endLine, silent) {
    // Логика обработки блока с использованием opts.marker и opts.className
  });
}

Использование Object.assign гарантирует, что все недостающие поля будут подставлены из defaultOptions. Этот подход делает плагин устойчивым к ошибкам и удобным для повторного использования.

Динамическая обработка опций

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

function toggleablePlugin(md, initialOptions = {}) {
  let options = { ...initialOptions };

  md.toggleOptions = function(newOptions) {
    options = { ...options, ...newOptions };
  };

  md.renderer.rules.custom = function(tokens, idx) {
    const token = tokens[idx];
    return `<span style="color:${options.color || 'black'}">${token.content}</span>`;
  };
}

Теперь опции можно изменять после инициализации:

md.use(toggleablePlugin, { color: 'red' });
md.toggleOptions({ color: 'blue' });

Валидация и безопасное использование опций

Для предотвращения ошибок рекомендуется:

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

Пример строгой проверки:

const opts = {
  color: typeof options.color === 'string' ? options.color : 'black',
  render: typeof options.render === 'function' ? options.render : content => content
};

Интеграция с другими плагинами

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

  • md.block.ruler.before(name, newRule, options) — вставка правила до существующего.
  • md.block.ruler.after(name, newRule, options) — вставка после.
  • md.inline.ruler.before/after — аналогично для inline-токенов.

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

Обработка сложных структур

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

  • nesting — обозначает начало (1) и конец (-1) блока.
  • map — массив строк [startLine, endLine] для правильного отображения в исходном тексте.
  • children — массив вложенных токенов для inline-структур.

Пример генерации вложенного блока:

function nestedPlugin(md, options = {}) {
  md.block.ruler.before('fence', 'nested_block', (state, startLine, endLine, silent) => {
    const tokenOpen = state.push('nested_open', 'div', 1);
    tokenOpen.attrs = [['class', options.className || 'nested']];
    
    const tokenContent = state.push('inline', '', 0);
    tokenContent.content = state.getLines(startLine, endLine, 0, true);
    
    const tokenClose = state.push('nested_close', 'div', -1);
    return true;
  });
}

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


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