Markdown-it — это высокопроизводительная библиотека для парсинга Markdown в JavaScript, которая поддерживает расширяемую систему инлайн-правил. Инлайн-правила обрабатывают элементы текста, которые находятся внутри строки, такие как ссылки, выделение текста, изображения, эмодзи (если включены плагины), и позволяют точно управлять процессом разметки.
Инлайн-правила работают на уровне токенизации, превращая последовательности символов в токены, которые затем могут быть преобразованы в HTML. В отличие от блочных правил, которые обрабатывают отдельные абзацы или блоки, инлайн-правила анализируют текст побайтно, что позволяет:
*, _) для выделения
текста;[текст](url);;Каждое правило инлайна в Markdown-it имеет следующую структуру:
function inlineRule(state, silent) {
// state — объект состояния парсинга
// silent — флаг проверки без генерации токенов
}
state — объект StateInline,
содержащий:
src — исходная строка текста;pos — текущая позиция в тексте;posMax — конец обрабатываемого сегмента;pending — текст, который пока не преобразован в
токены;push, skipToken и др., для
управления токенами.silent — логический параметр, который позволяет проверять наличие шаблона без записи токена. Используется для lookahead-проверок.
Функция должна вернуть true, если правило успешно
обработало текст, и false в противном случае.
Markdown-it использует правило emphasis для обработки
* и _. Основная логика заключается в поиске
закрывающего символа и генерации соответствующих
токенов:
const md = require('markdown-it')();
const src = 'Это *выделенный* текст';
const tokens = md.parseInline(src, {});
console.log(tokens);
Результат будет включать токены типа em_open,
text, em_close, что позволяет HTML-рендереру
преобразовать их в <em>выделенный</em>.
Markdown-it позволяет расширять парсер через метод
md.inline.ruler.before или
md.inline.ruler.after. Пример создания правила для
распознавания ++выделение++:
function highlightRule(state, silent) {
const start = state.pos;
if (state.src[start] !== '+' || state.src[start + 1] !== '+') return false;
let end = state.src.indexOf('++', start + 2);
if (end === -1) return false;
if (!silent) {
const tokenOpen = state.push('mark_open', 'mark', 1);
tokenOpen.markup = '++';
const tokenText = state.push('text', '', 0);
tokenText.content = state.src.slice(start + 2, end);
const tokenClose = state.push('mark_close', 'mark', -1);
tokenClose.markup = '++';
}
state.pos = end + 2;
return true;
}
md.inline.ruler.before('emphasis', 'highlight', highlightRule);
После этого текст ++важное++ будет преобразован в HTML
<mark>важное</mark>.
Инлайн-правила выполняются последовательно, согласно
порядку, заданному в md.inline.ruler. Встроенные правила
можно перемещать, отключать или добавлять новые:
emphasis — обработка * и
_;link — ссылки [text](url);image — изображения ;code — инлайновый код `code`;text — любой оставшийся текст.Правила могут взаимодействовать через state.pos и
state.pending, поэтому важно учитывать
последовательность, чтобы новые правила не ломали
существующие.
Инлайн-правила активно используют объект состояния для управления токенами:
state.push(type, tag, nesting) — добавляет новый
токен;state.delimiters — массив активных открывающих символов
(для вложенных элементов);state.skipToken(len) — сдвигает текущую позицию без
создания токена;state.pending += 'текст' — накапливает текст, который
не был распознан как правило.Markdown-it поддерживает рекурсивный вызов парсера для вложенных элементов:
const innerTokens = md.inline.parse('текст *с выделением*', md.options, {});
Это позволяет создавать сложные конструкции вроде:
++важное *и выделенное*++
которые будут корректно обработаны как
<mark>важное <em>и выделенное</em></mark>.
Для больших текстов важно учитывать:
silent для проверки шаблонов без создания
токенов уменьшает накладные расходы;state.push и манипуляций с
state.pending ускоряет процесс;Markdown-it имеет развитую систему плагинов, позволяющую добавлять новые инлайн-правила без изменения ядра. Примеры:
markdown-it-emoji — распознавание
:smile:;markdown-it-footnote — ссылки на сноски;markdown-it-ins — поддержка <ins>
для ++текст++.Плагин регистрирует инлайн-правило через md.inline.ruler
и при необходимости подключает кастомный рендер для HTML.
Парсер проходит текст символ за символом.
Проверяет применимость каждого инлайн-правила.
Если правило сработало:
state.pos продвигается.Если правило не сработало:
Нераспознанный текст добавляется как токен
text.
Полученные токены передаются HTML-рендереру для генерации финального результата.
Инлайн-правила в Markdown-it предоставляют гибкий и мощный инструмент для детальной обработки текста. Они позволяют реализовать как стандартные элементы Markdown, так и сложные кастомные синтаксические конструкции, управляя каждым символом на лету и поддерживая вложенность элементов.