Marked — это высокопроизводительная библиотека для парсинга Markdown в JavaScript. Она обеспечивает гибкость и скорость преобразования текста в HTML, а также позволяет детально управлять процессом разборки текста. Одним из продвинутых методов работы с Marked является мультипроходный парсинг, когда исходный Markdown обрабатывается несколькими этапами для достижения большей гибкости или для внедрения нестандартной логики.
Мультипроходный парсинг подразумевает несколько последовательных проходов по исходному тексту Markdown:
Такой подход особенно полезен при необходимости:
Первый проход отвечает за токенизацию Markdown.
Marked предоставляет функцию marked.lexer, которая
преобразует исходный текст в массив токенов:
import { marked } from 'marked';
const markdownText = `
# Заголовок 1
Параграф с **жирным** текстом и [ссылкой](https://example.com).
`;
const tokens = marked.lexer(markdownText);
console.log(tokens);
Токены имеют структуру объектов с полями, такими как:
type — тип токена (heading,
paragraph, list, code и
т.д.).text — текстовое содержимое токена.depth — уровень заголовка (для
heading).tokens — вложенные токены (для сложных блоков, таких
как списки или блоки кода).Первый проход позволяет детально анализировать структуру Markdown до генерации HTML.
После токенизации можно выполнить модификацию токенов, чтобы внедрить кастомные правила:
tokens.forEach(token => {
if (token.type === 'heading' && token.depth === 1) {
token.text = `? ${token.text}`; // добавление эмблемы к заголовкам первого уровня
}
if (token.type === 'paragraph') {
token.text = token.text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>'); // кастомная обработка жирного текста
}
});
Особенности промежуточной обработки:
Второй проход превращает обработанные токены в HTML
с использованием функции marked.parser:
const html = marked.parser(tokens);
console.log(html);
На этом этапе Marked выполняет:
Для полного контроля над HTML можно использовать кастомный Renderer:
const renderer = {
heading(text, level) {
return `<h${level} class="custom-heading">${text}</h${level}>`;
},
link(href, title, text) {
return `<a href="${href}" title="${title || ''}" target="_blank">${text}</a>`;
}
};
const htmlWithRenderer = marked.parser(tokens, { renderer });
Такой подход идеально подходит для мультипроходного парсинга:
Marked поддерживает интеграцию с плагинами или middleware, что делает мультипроходный парсинг более гибким:
Пример подключения подсветки кода:
import hljs from 'highlight.js';
const renderer = {
code(code, lang) {
const validLang = hljs.getLanguage(lang) ? lang : 'plaintext';
const highlighted = hljs.highlight(code, { language: validLang }).value;
return `<pre><code class="hljs ${validLang}">${highlighted}</code></pre>`;
}
};
const htmlHighlighted = marked.parser(tokens, { renderer });
Мультипроходный парсинг делает Marked не просто инструментом конвертации Markdown в HTML, а полноценной платформой для сложной обработки текстового контента в веб-приложениях.