Библиотека Markdown-it предоставляет мощную систему
для обработки и анализа Markdown-текста. Основой этой системы являются
три ключевых класса состояния: StateCore,
StateBlock и StateInline. Они управляют
процессом токенизации и рендеринга текста на разных уровнях, обеспечивая
гибкую и расширяемую архитектуру парсера.
StateCore — это центральный объект состояния, который
используется при выполнении цепочки core rules. Основная задача
StateCore — управлять списком токенов и обеспечивать
возможность их изменения на глобальном уровне после первичной обработки
документа.
Основные свойства:
src — исходный Markdown-текст.env — объект окружения, который может хранить любые
данные, необходимые для обработки.tokens — массив токенов, который формируется на этапе
парсинга и модифицируется core rules.inlineMode — логический флаг, указывающий, находится ли
обработка в контексте inline-уровня.Методы и функционал:
push(token) — добавляет токен в массив
tokens.walkTokens(fn) — обходит все токены и применяет функцию
fn к каждому.getTokens() — возвращает массив токенов для внешнего
использования.Пример использования:
const md = require('markdown-it')();
md.core.ruler.push('example_core_rule', function(state) {
state.tokens.push(new state.Token('custom_token', '', 0));
});
В этом примере создается core rule, которая добавляет пользовательский токен в конце массива.
StateBlock управляет обработкой блоков Markdown:
заголовков, параграфов, списков, цитат, кодовых блоков. Он используется
парсером для построения иерархии блоков и генерации соответствующих
токенов.
Основные свойства:
src — исходный текст для блока.bMarks — массив индексов начала каждой строки
блока.eMarks — массив индексов конца каждой строки
блока.tShift — массив отступов строк.blkIndent — текущий уровень отступа блока.lineMax — индекс последней строки документа.line — текущая строка для обработки.tokens — массив токенов, которые генерируются для
блока.Ключевые методы:
skipEmptyLines() — пропускает пустые строки и обновляет
индекс текущей строки.getLines(begin, end, indent, keepLastLF) — возвращает
массив строк блока с учетом отступов.push(type, tag, nesting) — создает и добавляет новый
токен блока.tokenize(state, startLine, endLine) — основной метод
для создания токенов из блока текста.Пример обработки блока кода:
function fenceBlock(state, startLine, endLine, silent) {
const pos = state.bMarks[startLine] + state.tShift[startLine];
const max = state.eMarks[startLine];
const lineText = state.src.slice(pos, max);
if (!lineText.startsWith('```')) return false;
if (!silent) {
const token = state.push('fence', 'code', 0);
token.content = state.getLines(startLine + 1, endLine, 0, true);
}
state.line = endLine;
return true;
}
Этот пример показывает, как StateBlock управляет
извлечением строк блока и генерацией токена fence.
StateInline отвечает за обработку
inline-содержимого внутри блоков. Это могут быть жирный
текст, ссылки, эмодзи, изображения и другие inline-элементы. Он работает
на уровне текста внутри блоков и преобразует их в токены, которые затем
рендерятся в HTML.
Основные свойства:
src — текст, который нужно разобрать на
inline-токены.pos — текущая позиция парсера внутри строки.posMax — конечная позиция для обработки.env — объект окружения для inline-уровня.tokens — массив сгенерированных inline-токенов.Ключевые методы:
push(type, tag, nesting) — добавляет новый
inline-токен.scanDelims(state, pos) — проверяет наличие
символов-разделителей (например, * для жирного текста) и
возвращает информацию о допустимых открывающих и закрывающих
позициях.tokenize(state) — основной метод для рекурсивного
разбиения текста на inline-токены.Пример обработки выделенного текста:
function strongRule(state, silent) {
const start = state.pos;
if (state.src[start] !== '*' || state.src[start + 1] !== '*') return false;
if (!silent) {
const token = state.push('strong_open', 'strong', 1);
state.pos += 2;
token = state.push('text', '', 0);
token.content = 'выделенный текст';
state.push('strong_close', 'strong', -1);
}
state.pos += 2;
return true;
}
Этот пример демонстрирует, как StateInline управляет
распознаванием и генерацией токенов для жирного текста.
Последовательность работы выглядит следующим образом:
StateCore.StateCore запускает block parser, который
создает StateBlock для каждого блока.StateBlock вызывает StateInline для
обработки inline-содержимого внутри блоков.StateCore.tokens для
последующего рендеринга или модификации.Эта система обеспечивает мощный и гибкий механизм обработки Markdown.
Понимание структуры StateCore, StateBlock и
StateInline позволяет создавать собственные правила,
расширения и плагины для Markdown-it, полностью контролируя процесс
парсинга на любом уровне.