Библиотека Marked в JavaScript предоставляет мощный движок для парсинга Markdown в HTML, основанный на модульной архитектуре. Центральным компонентом работы является токенизация: преобразование исходного Markdown-текста в последовательность токенов, которые затем обрабатываются рендерером. Стандартная токенизация охватывает большинство типичных конструкций Markdown, но иногда требуется расширить возможности парсинга для поддержки кастомных синтаксических форматов.
Токенизатор в Marked представлен как набор методов, каждый из которых отвечает за распознавание определённых элементов Markdown:
Каждый метод возвращает объект токена с набором полей:
{
type: 'heading', // тип токена
depth: 2, // уровень заголовка
text: 'Пример' // текст содержимого
}
Если токен не распознан, метод возвращает false,
позволяя токенизатору проверять другие правила.
Расширение стандартной токенизации начинается с наследования
стандартного токенизатора или создания собственного класса,
совместимого с API Marked. Для этого используется объект
Tokenizer:
const { Tokenizer } = require('marked');
class CustomTokenizer extends Tokenizer {
// Метод для распознавания кастомного блока
customBlock(src) {
const match = /^:::(.+?)\n([\s\S]+?)\n:::/m.exec(src);
if (match) {
return {
type: 'custom',
name: match[1].trim(),
text: match[2].trim(),
raw: match[0]
};
}
return false;
}
}
Принцип работы: метод получает исходный текст
(src) и пытается сопоставить его с регулярным выражением.
Если совпадение найдено, создается токен с полями type,
raw и любыми дополнительными параметрами. Если совпадения
нет — возвращается false.
Для того чтобы Marked начал использовать новый токенизатор, необходимо передать его в конфигурацию:
const marked = require('marked');
const tokenizer = new CustomTokenizer();
marked.use({ tokenizer });
const markdown = `
:::note
Это важное сообщение
:::
`;
console.log(marked.parse(markdown));
В результате кастомный блок будет правильно распознан и обработан стандартным рендерером.
Inline-токены работают аналогично блоковым, но применяются внутри строки текста. Пример добавления поддержки кастомного эмфазиса с двойными звездочками:
class InlineTokenizer extends Tokenizer {
strongDouble(src) {
const match = /^\*\*(.+?)\*\*/.exec(src);
if (match) {
return {
type: 'strongDouble',
raw: match[0],
text: match[1]
};
}
return false;
}
}
marked.use({ tokenizer: new InlineTokenizer() });
Токен strongDouble будет интегрирован в
последовательность inline-токенов и передан рендереру.
После создания токена важно определить, как он будет визуализирован.
Для этого используется объект Renderer:
const renderer = {
custom(token) {
return `<div class="custom-block" data-name="${token.name}">${token.text}</div>`;
},
strongDouble(token) {
return `<strong class="double-strong">${token.text}</strong>`;
}
};
marked.use({ renderer });
Каждое поле объекта соответствует типу токена. Marked вызывает соответствующий метод при рендеринге, обеспечивая гибкость отображения.
Для корректной работы расширенного токенизатора необходимо учитывать порядок применения правил:
Это предотвращает конфликт распознавания с базовыми Markdown-конструкциями.
Регулярные выражения — основной инструмент при создании кастомных токенов. Важно:
/m) для блоков;raw, чтобы Marked корректно
заменял исходный текст на токен;Это пример текста с[^1] сноской.
[^1]: Текст сноски
:::warning
Опасность!
:::
==выделение==.Для каждой конструкции создается токен с кастомным методом в токенизаторе и соответствующий рендерер.
Marked позволяет комбинировать несколько токенизаторов и рендереров
через use(), что открывает возможность создания
модульной системы расширений. Это особенно полезно для
интеграции:
Расширение стандартной токенизации делает библиотеку Marked гибким инструментом для реализации любых Markdown-сценариев, сохраняя при этом совместимость с существующими стандартами.