Markdown-it представляет собой мощный парсер Markdown на JavaScript с поддержкой гибкой кастомизации. Центральным элементом его архитектуры является цепочка правил (rule chain), которая отвечает за преобразование текста Markdown в HTML. Каждый этап обработки текста можно модифицировать, добавлять новые правила или удалять существующие, что делает Markdown-it крайне адаптивным инструментом.
Цепочка правил состоит из двух основных фаз:
Каждая фаза представлена массивом функций, называемых
правилами. Каждое правило принимает на вход объект
состояния (state) и выполняет свою задачу: модифицирует
массив токенов или добавляет новые токены, которые затем используются
для генерации HTML.
Регистрация правил осуществляется с помощью методов
md.core.ruler, md.block.ruler и
md.inline.ruler.
md.block.ruler.before('paragraph', 'my_custom_block', function(state, startLine, endLine, silent) {
// логика обработки блока
});
md.inline.ruler.after('emphasis', 'my_custom_inline', function(state, silent) {
// логика обработки встроенного элемента
});
md.core.ruler.push('my_core_rule', function(state) {
// модификация state.tokens
});
Параметры методов регистрации:
before(name, ruleName, fn) – вставляет правило перед
существующим.after(name, ruleName, fn) – вставляет правило после
существующего.push(ruleName, fn) – добавляет правило в конец
цепочки.fn – функция правила с определённой сигнатурой.function(state, startLine, endLine, silent)
state – объект состояния документа.
startLine и endLine – номера строк в
исходном тексте.
silent – режим проверки (без фактического добавления
токенов).
Встроенные правила:
function(state, silent)
function(state)
Здесь state.tokens содержит массив токенов, с которыми
можно производить любые операции: вставлять, удалять, менять
порядок.
Markdown-it обрабатывает правила в строгом порядке, который
определяется последовательностью их регистрации. Использование методов
before и after позволяет точно
контролировать позицию нового правила относительно
существующих:
md.block.ruler.before('heading', 'custom_title_block', customBlockFunction);
Это гарантирует, что custom_title_block будет выполнено
до обработки заголовков, что важно для кастомных
синтаксисов, которые должны преобразовываться заранее.
Существующие правила можно удалять и переопределять через методы:
md.block.ruler.disable(['paragraph', 'blockquote']);
md.block.ruler.enable(['paragraph']);
Это позволяет временно отключать стандартные правила или полностью заменять их на свои.
<note>:function noteBlock(state, startLine, endLine, silent) {
let pos = state.bMarks[startLine] + state.tShift[startLine];
let max = state.eMarks[startLine];
if (state.src.slice(pos, pos + 6) !== ':::note') return false;
if (silent) return true;
let token = state.push('note_open', 'div', 1);
token.attrs = [['class', 'note']];
state.line = startLine + 1;
token = state.push('note_close', 'div', -1);
return true;
}
md.block.ruler.before('paragraph', 'note_block', noteBlock);
==highlight==:function highlightInline(state, silent) {
const max = state.posMax;
const start = state.pos;
if (state.src.charCodeAt(start) !== 0x3D/* = */) return false;
if (start + 1 >= max || state.src.charCodeAt(start + 1) !== 0x3D) return false;
if (!silent) {
let token = state.push('highlight_open', 'mark', 1);
token = state.push('text', '', 0);
token.content = state.src.slice(start + 2, max - 2);
state.push('highlight_close', 'mark', -1);
}
state.pos = max;
return true;
}
md.inline.ruler.after('emphasis', 'highlight', highlightInline);
Каждое правило взаимодействует с массивом state.tokens.
Основные операции:
state.push(type, tag, nesting)state.tokens.splice(index, 1)token.content = 'новое содержимое'token.attrs = [['class', 'highlight']]Это даёт полную свободу в создании любых кастомных элементов Markdown и их последующем преобразовании в HTML.
state.tokens
внутри inline правил, чтобы не замедлять парсинг.silent для проверки корректности
синтаксиса без генерации токенов.Цепочка правил Markdown-it — это гибкий инструмент, который позволяет контролировать каждый шаг парсинга. Понимание порядка регистрации, сигнатур функций и работы с токенами открывает широкие возможности по расширению синтаксиса и созданию высокопроизводительных кастомных решений.