Markdown-it — это мощный парсер Markdown на JavaScript, который превращает текст в структурированное дерево токенов. Понимание вложенности токенов является ключевым моментом для реализации сложных функций, таких как пользовательские рендереры, плагины и обработка нестандартных синтаксических конструкций.
Парсер Markdown-it разбивает текст на массив токенов. Каждый токен имеет следующие ключевые свойства:
type — строка, указывающая тип токена, например,
paragraph_open, inline,
strong_open.
tag — HTML-тег, который будет использован при
рендеринге (p, strong, em и
т.д.).
nesting — число, указывающее уровень
вложенности:
1 — открывающий токен (например,
<p>),0 — самозакрывающийся или одиночный токен (например,
текст внутри параграфа),-1 — закрывающий токен (например,
</p>).children — массив дочерних токенов для
inline-элементов.
level — числовой показатель глубины вложенности в
общем массиве токенов.
content — текстовое содержимое токена, актуально для
токенов с nesting = 0.
Вложенность реализуется через комбинацию nesting и
children. Inline-токены (type = "inline")
содержат массив children, где находятся текстовые и
форматирующие токены.
Рассмотрим Markdown:
**Жирный текст с _курсивом_ внутри**
После парсинга Markdown-it создаёт следующие токены:
1. strong_open, tag: "strong", nesting: 1
2. inline, content: "Жирный текст с _курсивом_ внутри", children: [
2.1 text: "Жирный текст с ", nesting: 0
2.2 em_open, tag: "em", nesting: 1
2.3 text: "курсивом", nesting: 0
2.4 em_close, tag: "em", nesting: -1
2.5 text: " внутри", nesting: 0
]
3. strong_close, tag: "strong", nesting: -1
Здесь видно, что inline токен является
контейнером для вложенных токенов, а каждый открывающий/закрывающий
токен поддерживает правильную структуру HTML.
Свойство level помогает определять текущую глубину.
Пример использования:
const md = require('markdown-it')();
const tokens = md.parse('**Текст с _вложенным_ элементом**', {});
tokens.forEach(token => {
console.log(`${' '.repeat(token.level * 2)}${token.type} (${token.nesting})`);
});
Вывод покажет визуально, как каждый токен находится на разных уровнях. Это особенно полезно при создании собственных рендереров, чтобы корректно обрабатывать вложенные структуры.
Inline-токены часто содержат текстовые узлы и другие inline-токены. Пример:
const inlineToken = tokens[1]; // inline токен
inlineToken.children.forEach(child => {
console.log(child.type, child.content);
});
При работе с children можно реализовать трансформации
текста, вставку HTML, замену элементов или анализ сложных
Markdown-конструкций без нарушения структуры.
u_open и u_close токены
внутрь inline.children.open → inline → close.level и
nesting для построения корректного DOM при рендеринге.nesting = 0 не имеют дочерних токенов, но
могут содержать текст в content.children.Пример обхода токенов с учётом вложенности:
function printTokens(tokens, indent = 0) {
tokens.forEach(token => {
console.log(`${' '.repeat(indent)}${token.type} (${token.nesting})`);
if (token.children) {
printTokens(token.children, indent + 2);
}
});
}
printTokens(tokens);
Этот подход позволяет наглядно увидеть всю иерархию элементов Markdown, что критично при написании кастомных парсеров и обработчиков.
Markdown-it строит HTML на основе вложенных токенов:
Поддержание корректной вложенности гарантирует валидный HTML, правильное оформление и отсутствие конфликтов между стилями.
Вложенность токенов в Markdown-it — это фундаментальный механизм,
обеспечивающий точное преобразование Markdown в HTML. Понимание
nesting, children и level
позволяет реализовывать сложные расширения и контролировать внутреннюю
структуру документа на уровне токенов.