В Markdown-it любой процесс обработки текста начинается с лексического анализа, который превращает входной Markdown в последовательность токенов. Токены — это структуры, описывающие блоки или inline-элементы разметки, включая их тип, содержимое и дополнительные атрибуты. Понимание и создание токенов является ключевым для разработки собственных плагинов и расширений.
Токен в Markdown-it представляет собой объект с определёнными полями:
paragraph_open, inline,
text.p, strong, em и т.д.).[["class", "highlight"]].[startLine, endLine].1 для
открывающего тега, -1 для закрывающего, 0 для
самостоятельного.inline элементов).Пример создания базового текстового токена:
const token = new state.Token('text', '', 0);
token.content = 'Пример текста';
Для добавления нового блокового элемента создаётся
открывающий токен, затем при необходимости
вложенные токены, и закрывающий токен. Например, для
создания блока с пользовательским тегом note:
const openToken = new state.Token('note_open', 'div', 1);
openToken.attrs = [['class', 'note']];
openToken.map = [startLine, endLine];
const contentToken = new state.Token('inline', '', 0);
contentToken.content = 'Содержимое блока note';
contentToken.children = [];
const closeToken = new state.Token('note_close', 'div', -1);
state.tokens.push(openToken, contentToken, closeToken);
Ключевой момент: правильная установка поля
nesting. Оно определяет, как Markdown-it будет
интерпретировать токен при генерации HTML. Ошибка в nesting
может привести к некорректному рендерингу или пропуску содержимого.
Inline-токены отвечают за форматирование внутри строки:
жирный, курсив, ссылки, изображения. Их создают внутри
inline токена через поле children.
Пример создания выделенного текста:
const inlineToken = new state.Token('inline', '', 0);
const strongOpen = new state.Token('strong_open', 'strong', 1);
const text = new state.Token('text', '', 0);
text.content = 'Выделенный текст';
const strongClose = new state.Token('strong_close', 'strong', -1);
inlineToken.children = [strongOpen, text, strongClose];
state.tokens.push(inlineToken);
Каждый токен может содержать массив атрибутов. Атрибуты хранятся в
виде массивов [имя, значение]. Для добавления или изменения
атрибута:
token.attrs = token.attrs || [];
token.attrs.push(['id', 'custom-id']);
Для поиска и модификации существующего атрибута:
const index = token.attrs.findIndex(attr => attr[0] === 'class');
if (index >= 0) {
token.attrs[index][1] += ' additional-class';
}
При разработке плагина создаются новые правила для
блоков или inline-элементов. Для блоков добавляют правило в
md.block.ruler, для inline — в
md.inline.ruler. Правило — это функция с сигнатурой:
function myBlockRule(state, startLine, endLine, silent) {
// 1. Проверка условия
// 2. Создание открывающего токена
// 3. Создание контентных токенов
// 4. Создание закрывающего токена
return true; // если блок успешно обработан
}
Пример добавления правила:
md.block.ruler.before('paragraph', 'note_block', myBlockRule);
Внутри функции state.tokens.push(...) добавляются все
необходимые токены, а state.line обновляется для перехода к
следующей необработанной строке.
state.tokens.1
открывающий, -1 закрывающий, 0
самостоятельный.Создание токенов — это фундамент расширений Markdown-it. Понимание их структуры и правильное использование открывает возможности для создания сложных кастомных блоков и элементов, полностью интегрированных с системой рендеринга.