В ядре библиотеки Markdown-it каждый элемент
синтаксического дерева представлен объектом токена
(Token). Эти токены содержат информацию о типе элемента,
его содержимом, позициях в исходном тексте и дополнительных свойствах,
включая атрибуты, которые управляют генерацией HTML.
Работа с атрибутами токенов является ключевой для расширений Markdown,
создания плагинов и детальной настройки вывода.
Каждый токен в Markdown-it имеет базовые поля:
type — тип токена, например
'paragraph_open', 'heading_close',
'inline'.tag — HTML-тег, который будет сгенерирован
('p', 'h1', 'strong' и
т.д.).attrs — массив атрибутов, представленных в виде массива
[ключ, значение].content — текст внутри токена (актуально для
inline-токенов).children — массив дочерних токенов (для
inline-структур).level — глубина вложенности токена.markup — оригинальный Markdown-разметочный символ,
например '#' для заголовков.info — дополнительная информация (например, язык в
блоках кода).Поле attrs отвечает за атрибуты HTML-элемента, которые
будут вставлены при рендеринге.
{
type: 'link_open',
tag: 'a',
attrs: [['href', 'https://example.com'], ['title', 'Пример ссылки']],
content: '',
children: [],
level: 0,
markup: '[]()'
}
В этом примере токен link_open содержит два атрибута:
href и title.
Добавление атрибутов осуществляется путем изменения массива
attrs. Если массив пуст, его необходимо
инициализировать:
token.attrs = token.attrs || [];
token.attrs.push(['target', '_blank']);
Это добавляет атрибут target="_blank" к HTML-элементу,
создаваемому токеном. Если атрибут с таким именем уже существует,
следует обновлять значение вместо добавления дубликата.
Для безопасного изменения атрибутов применяется поиск по ключу:
function setAttr(token, name, value) {
token.attrs = token.attrs || [];
const index = token.attrs.findIndex(attr => attr[0] === name);
if (index !== -1) {
token.attrs[index][1] = value;
} else {
token.attrs.push([name, value]);
}
}
// Пример:
setAttr(token, 'class', 'highlight');
Такая функция гарантирует уникальность каждого атрибута.
Удаление выполняется через фильтрацию массива:
function removeAttr(token, name) {
token.attrs = token.attrs || [];
token.attrs = token.attrs.filter(attr => attr[0] !== name);
}
// Пример:
removeAttr(token, 'title');
После вызова данного метода указанный атрибут будет полностью удалён из токена.
Большинство плагинов Markdown-it используют токены для модификации HTML. Примеры распространённых операций:
md.core.ruler.push('add_heading_class', state => {
state.tokens.forEach(token => {
if (token.type === 'heading_open') {
setAttr(token, 'class', `heading-level-${token.tag.slice(1)}`);
}
});
});
md.core.ruler.push('external_links', state => {
state.tokens.forEach(token => {
if (token.type === 'link_open') {
setAttr(token, 'rel', 'noopener noreferrer');
setAttr(token, 'target', '_blank');
}
});
});
md.core.ruler.push('image_class', state => {
state.tokens.forEach(token => {
if (token.type === 'image') {
setAttr(token, 'class', 'responsive-image');
}
});
});
При кастомизации рендеринга HTML можно напрямую использовать поле
attrs. Пример функции рендера для ссылок:
md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
const token = tokens[idx];
const attrs = token.attrs ? token.attrs.map(a => `${a[0]}="${a[1]}"`).join(' ') : '';
return `<a ${attrs}>`;
};
Этот подход позволяет полностью контролировать итоговый HTML без изменения исходного Markdown.
Inline-токены часто содержат вложенные элементы
(children), у которых также могут быть атрибуты. Для
массового изменения атрибутов внутри inline-токена необходимо рекурсивно
обходить children:
function setClassRecursively(tokens, className) {
tokens.forEach(token => {
setAttr(token, 'class', className);
if (token.children) {
setClassRecursively(token.children, className);
}
});
}
Это особенно важно при работе с форматированным текстом
(strong, em, code), где атрибуты
могут добавляться на всех уровнях вложенности.
attrs перед
добавлением: многие токены по умолчанию имеют
null.core.ruler для глобальной модификации токенов до
рендеринга.Атрибуты токенов предоставляют полное управление HTML-разметкой, генерируемой Markdown-it, и являются основой для создания сложных расширений и кастомных стилей.