Markdown-it — это гибкая и расширяемая библиотека для парсинга Markdown в JavaScript. Одной из ключевых возможностей является кастомизация вывода, позволяющая изменять результат рендеринга, управлять HTML-тегами и создавать собственные правила для обработки контента.
Markdown-it использует объект renderer для
преобразования токенов в HTML. Каждый тип токена имеет соответствующий
метод рендеринга.
const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();
md.renderer.rules.paragraph_open = (tokens, idx) => {
return '<p class="custom-paragraph">';
};
md.renderer.rules.paragraph_close = () => '</p>';
const result = md.render('Пример параграфа.');
console.log(result);
// <p class="custom-paragraph">Пример параграфа.</p>
Ключевой момент: можно переопределять любые
стандартные правила, включая заголовки
(heading_open/heading_close), ссылки
(link_open/link_close) и изображения
(image).
Markdown-it поддерживает кастомные токены, что позволяет добавлять нестандартные элементы Markdown.
md.core.ruler.push('highlight_text', function(state) {
state.tokens.forEach(token => {
if (token.type === 'inline') {
token.children.forEach(child => {
if (child.type === 'text' && child.content.includes('IMPORTANT')) {
child.type = 'html_inline';
child.content = `<span class="highlight">${child.content}</span>`;
}
});
}
});
});
const html = md.render('Это IMPORTANT текст.');
console.log(html);
// <p>Это <span class="highlight">IMPORTANT</span> текст.</p>
Принцип работы:
core.ruler или
block/ruler_inline.html_inline или
html_block.С помощью renderer.rules можно изменять атрибуты ссылок
и картинок.
md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
const hrefIndex = tokens[idx].attrIndex('href');
if (hrefIndex >= 0) {
tokens[idx].attrs[hrefIndex][1] = tokens[idx].attrs[hrefIndex][1] + '?ref=custom';
}
tokens[idx].attrPush(['target', '_blank']);
return self.renderToken(tokens, idx, options);
};
const htmlLink = md.render('[Сайт](https://example.com)');
console.log(htmlLink);
// <p><a href="https://example.com?ref=custom" target="_blank">Сайт</a></p>
Особенности:
attrIndex проверяет, существует ли атрибут.attrPush добавляет новый атрибут.self.renderToken используется для стандартного
рендеринга после изменений.Markdown-it поддерживает плагины, которые позволяют интегрировать новые синтаксические конструкции или изменять существующие.
function emoji_plugin(md) {
const emojiMap = { ':smile:': '?', ':heart:': '❤️' };
md.core.ruler.push('emoji_replace', state => {
state.tokens.forEach(token => {
if (token.type === 'inline') {
token.children.forEach(child => {
if (child.type === 'text') {
Object.keys(emojiMap).forEach(code => {
child.content = child.content.replaceAll(code, emojiMap[code]);
});
}
});
}
});
});
}
md.use(emoji_plugin);
console.log(md.render('Привет :smile: :heart:'));
// <p>Привет ? ❤️</p>
Принцип:
core.ruler для изменения контента до
финального рендеринга.fence и
code_blockДля блоков кода можно изменить HTML-структуру или добавить подсветку:
md.renderer.rules.fence = (tokens, idx) => {
const token = tokens[idx];
const langClass = token.info ? ` class="language-${token.info}"` : '';
return `<pre${langClass}><code>${token.content}</code></pre>`;
};
const codeHtml = md.render('```js\nconsole.log("Hello");\n```');
console.log(codeHtml);
// <pre class="language-js"><code>console.log("Hello");</code></pre>
Важные моменты:
token.info содержит указание языка (если есть).token.content — исходный код блока.Markdown-it поддерживает строгий контроль вывода через опцию
html и использование фильтров:
const mdSafe = new MarkdownIt({ html: false });
const unsafeHtml = mdSafe.render('<script>alert("XSS")</script>');
console.log(unsafeHtml);
// <script>alert("XSS")</script>
Рекомендации по безопасности:
html: false для блокировки raw HTML.sanitize-html или аналогичные
библиотеки для дополнительной фильтрации.Для полноценной кастомизации рекомендуется комбинировать:
renderer.rules) — для
управления HTML-выводом конкретных токенов.use) — для внедрения новых
конструкций Markdown.core.ruler,
inline.ruler) — для изменения содержания токенов
на этапе парсинга.html,
xhtmlOut) — для предотвращения внедрения
небезопасного HTML.Такой подход позволяет полностью контролировать, как Markdown преобразуется в HTML, создавая как минималистичный чистый код, так и сложные кастомные элементы с динамическими атрибутами и стилями.