Библиотека Marked предоставляет мощный и гибкий механизм для работы с Markdown в JavaScript. Одним из ключевых элементов расширяемости является возможность создания расширений инлайн-уровня, которые позволяют вмешиваться в процесс обработки текста на уровне отдельных элементов Markdown, таких как ссылки, эмодзи, выделения и другие inline-компоненты.
Инлайн-уровень означает работу с элементами, находящимися внутри строки текста, в отличие от блочного уровня, который оперирует параграфами, списками или таблицами. Расширения инлайн-уровня дают возможность определять новые синтаксические конструкции, изменять стандартную обработку или добавлять дополнительные атрибуты к существующим элементам.
Расширение инлайн-уровня в Marked представляет собой объект с несколькими обязательными и опциональными свойствами:
{
name: 'название_расширения',
level: 'inline',
start?: Function,
tokenizer: Function,
renderer?: Function
}
'inline'.Для демонстрации создадим расширение, которое обрабатывает текст вида
++выделение++ и преобразует его в
<mark>:
const highlightExtension = {
name: 'highlight',
level: 'inline',
start(src) {
return src.indexOf('++');
},
tokenizer(src) {
const rule = /^\+\+([^\+]+)\+\+/;
const match = rule.exec(src);
if (match) {
return {
type: 'highlight',
raw: match[0],
text: match[1]
};
}
},
renderer(token) {
return `<mark>${token.text}</mark>`;
}
};
start помогает библиотеке быстро найти потенциальное
место для токена, избегая лишних проверок всего текста.tokenizer проверяет соответствие регулярному выражению
и возвращает объект с типом токена, исходной строкой и содержимым.renderer преобразует токен в HTML-разметку
<mark>.Для активации расширения необходимо зарегистрировать его при парсинге:
import { marked } from 'marked';
marked.use({ extensions: [highlightExtension] });
const result = marked('Это ++важный++ текст.');
console.log(result);
// Вывод: Это <mark>важный</mark> текст.
Расширения инлайн-уровня могут обрабатывать сложные конструкции,
такие как кастомные ссылки, эмодзи, математические формулы. В таких
случаях используются продвинутые возможности tokenizer:
const emojiExtension = {
name: 'emoji',
level: 'inline',
tokenizer(src) {
const rule = /^:([a-z_]+):/;
const match = rule.exec(src);
if (match) {
return {
type: 'emoji',
raw: match[0],
name: match[1]
};
}
},
renderer(token) {
const emojiMap = {
smile: '?',
heart: '❤️',
fire: '?'
};
return emojiMap[token.name] || token.raw;
}
};
:имя:.renderer использует словарь для подстановки символа
эмодзи. Если эмодзи не найдено, возвращается исходная строка.Marked обрабатывает текст последовательно. Важно учитывать приоритет расширений: расширения, зарегистрированные первыми, имеют более высокий приоритет при поиске токенов. Для инлайн-уровня это особенно важно, когда несколько расширений могут совпадать с одним участком текста.
Для корректной работы следует:
start для ускорения поиска.raw для точного подсчёта
оставшегося текста.Инлайн-уровень обрабатывает текст посимвольно, поэтому даже небольшие оптимизации могут существенно ускорить парсинг. Основные рекомендации:
start для ограничения области поиска.undefined для токенов, если соответствия
нет, чтобы библиотека переходила к следующему расширению.Marked позволяет регистрировать несколько инлайн-расширений одновременно:
marked.use({ extensions: [highlightExtension, emojiExtension] });
const result = marked('++Внимание++ :smile:');
console.log(result);
// Вывод: <mark>Внимание</mark> ?
Каждое расширение обрабатывает текст независимо, при этом библиотека соблюдает порядок регистрации, что обеспечивает предсказуемое поведение.
Помимо HTML, токены расширений могут использоваться для:
Пример добавления CSS-класса через расширение:
const boldExtension = {
name: 'customBold',
level: 'inline',
tokenizer(src) {
const match = /^\*\*([^\*]+)\*\*/.exec(src);
if (match) {
return { type: 'customBold', raw: match[0], text: match[1] };
}
},
renderer(token) {
return `<strong class="highlighted">${token.text}</strong>`;
}
};
Такой подход позволяет создавать гибкие стили и расширять Markdown под конкретные требования проекта.
Расширения инлайн-уровня в Marked дают полный контроль над обработкой
текстовых элементов Markdown. Правильное использование
tokenizer, renderer и start
обеспечивает высокую производительность, точное распознавание сложных
паттернов и гибкость кастомизации.