В библиотеке Markdown-it ключевым элементом процесса парсинга является токен. Токены представляют собой структурированные объекты, описывающие элементы исходного Markdown-кода, их тип, уровни вложенности и дополнительные атрибуты. Работа с токенами позволяет глубоко контролировать процесс преобразования Markdown в HTML и расширять стандартное поведение парсера.
Каждый токен в Markdown-it имеет следующие основные свойства:
type — строка, определяющая тип токена, например:
paragraph_open, inline,
heading_open.
tag — HTML-тег, соответствующий токену
(p, h1, ul и т.д.).
attrs — массив атрибутов
[ [имя, значение], ... ].
map — массив [startLine, endLine],
определяющий диапазон строк в исходном Markdown.
nesting — числовой флаг, определяющий
вложенность:
1 — открывающий тег,0 — самозакрывающийся,-1 — закрывающий тег.level — текущий уровень вложенности токена.
children — массив вложенных токенов (для токенов
типа inline).
content — текстовое содержимое, актуально для
текстовых и inline-токенов.
markup — символы разметки, которые использовались
(*, **, # и т.д.).
info — дополнительная информация, например, для
блоков кода это имя языка.
Пример токена для параграфа:
{
type: 'paragraph_open',
tag: 'p',
attrs: null,
map: [0, 1],
nesting: 1,
level: 0,
children: null,
content: '',
markup: '',
info: ''
}
После парсинга Markdown с помощью метода
md.parse(markdownString, env) получается массив токенов.
Работа с токенами обычно включает итерирование по
массиву, обработку children и применение
пользовательской логики.
const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();
const tokens = md.parse('# Заголовок\n\nПараграф текста.', {});
tokens.forEach(token => {
console.log(token.type, token.tag, token.level);
});
Здесь вывод покажет структуру документа с уровнями вложенности, что важно при модификации или создании собственных рендереров.
Токены можно изменять для кастомизации вывода:
tokens.forEach(token => {
if (token.type === 'heading_open') {
token.tag = 'h2';
}
});
tokens.forEach(token => {
if (token.type === 'paragraph_open') {
token.attrs = token.attrs || [];
token.attrs.push(['class', 'custom-paragraph']);
}
});
tokens.forEach(token => {
if (token.type === 'inline' && token.children) {
token.children.forEach(child => {
if (child.type === 'text') {
child.content = child.content.toUpperCase();
}
});
}
});
children
токеновInline-токены содержат массив children, которые
описывают текстовые и форматирующие элементы. Основные типы
children:
text — обычный текст.strong_open / strong_close — выделение
жирным.em_open / em_close — курсив.link_open / link_close — ссылки.code_inline — встроенный код.Пример обхода inline-токенов:
tokens.forEach(token => {
if (token.type === 'inline') {
token.children.forEach(child => {
if (child.type === 'code_inline') {
child.content = `Processed: ${child.content}`;
}
});
}
});
Часто требуется извлечь токены определенного типа. Для этого удобно
использовать filter:
const headings = tokens.filter(t => t.type.endsWith('_open') && t.tag.startsWith('h'));
headings.forEach(h => console.log(h.tag, h.content));
Так можно получить список всех заголовков документа или любых других элементов.
Markdown-it позволяет создавать новые токены для добавления нестандартной разметки:
const token = new md.Token('custom_block', 'div', 1);
token.attrs = [['class', 'highlight']];
token.content = 'Содержимое кастомного блока';
tokens.push(token);
// Добавление закрывающего токена
const closingToken = new md.Token('custom_block', 'div', -1);
tokens.push(closingToken);
Эта возможность открывает доступ к расширению Markdown без изменения исходного синтаксиса.
Плагины Markdown-it часто работают напрямую с токенами, чтобы:
Пример простого плагина, который добавляет класс всем ссылкам:
function addLinkClass(md) {
md.core.ruler.push('link_class', state => {
state.tokens.forEach(token => {
if (token.type === 'link_open') {
token.attrs = token.attrs || [];
token.attrs.push(['class', 'external-link']);
}
});
});
}
md.use(addLinkClass);
Здесь используется state.tokens — основной массив
токенов, который можно изменять на любом этапе парсинга.
Свойство level токена отражает глубину вложенности
элементов. Например:
0 — корневой блок документа.1 — параграф внутри документа.2 — текст внутри параграфа.Уровни вложенности помогают при генерации дерева HTML, при вставке новых блоков и при контроле структуры документа.
Методы работы с токенами в Markdown-it предоставляют полный контроль над процессом рендеринга. Понимание структуры токенов, их свойств и вложенности позволяет:
Использование токенов — это мощный инструмент, открывающий доступ к глубокой кастомизации Markdown-парсинга и рендеринга в JavaScript.