Markdown-it — это мощная библиотека для парсинга Markdown в JavaScript, которая преобразует исходный текст в структуру токенов. Токены представляют собой единицы синтаксического дерева, каждую из которых можно рассматривать как отдельный элемент Markdown-документа: заголовок, абзац, список, ссылку или inline-контент. Для эффективной работы с Markdown на низком уровне необходимо понимать структуру токенов и уметь навигировать по дереву.
Каждый токен в Markdown-it имеет несколько ключевых свойств:
paragraph_open, inline,
heading_close. Тип определяет синтаксическую роль
токена.p, h1, ul.[ключ, значение], применяемых к тегу. Может быть
null, если атрибутов нет.[startLine, endLine],
указывающий на строки исходного Markdown, которые соответствуют
токену.1 для открывающего
тега, -1 для закрывающего, 0 для
самозакрывающегося.Пример типичного токена:
{
type: 'paragraph_open',
tag: 'p',
attrs: null,
map: [0, 1],
nesting: 1,
level: 0,
children: null
}
Токены формируются при парсинге Markdown с помощью метода
parse объекта Markdown-it:
const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();
const tokens = md.parse('# Заголовок\n\nТекст абзаца', {});
console.log(tokens);
Метод parse возвращает массив токенов верхнего уровня.
Каждый элемент массива — отдельный токен с возможными дочерними токенами
в свойстве children.
Уровень вложенности (level) используется для построения
дерева токенов и навигации по нему.
Для навигации по дереву токенов используют циклы по массиву токенов и
рекурсивную обработку свойства children:
function traverseTokens(tokens, callback) {
tokens.forEach(token => {
callback(token);
if (token.children) {
traverseTokens(token.children, callback);
}
});
}
// Использование
traverseTokens(tokens, token => {
console.log('Тип токена:', token.type, 'Уровень:', token.level);
});
Markdown-it использует парные токены для блоков с
началом и концом: *_open и *_close.
Пример:
# Заголовок
При разборе формируются два токена:
heading_open с nesting: 1inline с текстом заголовкаheading_close с nesting: -1Соответствие открывающих и закрывающих токенов удобно отслеживать по уровню вложенности и порядку в массиве токенов.
Токены могут содержать атрибуты, определяющие HTML-свойства:
{
type: 'link_open',
tag: 'a',
attrs: [['href', 'https://example.com']],
nesting: 1
}
Для извлечения атрибутов удобно использовать вспомогательные функции:
function getAttr(token, name) {
if (!token.attrs) return null;
const attr = token.attrs.find(([key]) => key === name);
return attr ? attr[1] : null;
}
const href = getAttr(tokens[1], 'href');
Inline-токены (inline) содержат текст и вложенные
элементы, такие как эмодзи, ссылки или выделение. Их структура:
{
type: 'inline',
tag: '',
children: [
{ type: 'text', content: 'Пример текста', level: 1 },
{ type: 'strong_open', level: 1 },
{ type: 'text', content: 'жирный текст', level: 2 },
{ type: 'strong_close', level: 1 }
]
}
Обход children рекурсивно позволяет детально
анализировать содержимое блоков.
const headings = [];
traverseTokens(tokens, token => {
if (token.type.endsWith('_open') && token.tag.startsWith('h')) {
headings.push(token);
}
});
const links = [];
traverseTokens(tokens, token => {
if (token.type === 'link_open') {
links.push(getAttr(token, 'href'));
}
});
function extractText(tokens) {
let result = '';
traverseTokens(tokens, token => {
if (token.type === 'text') {
result += token.content;
}
});
return result;
}
children перед рекурсией.nesting и level для
идентификации парных токенов.level 0) обычно соответствуют
блочным элементам документа.Эта структура позволяет строить собственные плагины, расширять функционал Markdown-it и создавать инструменты для анализа и трансформации Markdown-документов на низком уровне.