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 предоставляет гибкий и мощный механизм управления опциями плагинов. Сочетание значений по умолчанию, валидаторов, динамических обновлений и контроля вложенности позволяет создавать расширяемые и безопасные расширения, адаптируемые под любые требования.