Библиотека Marked в JavaScript является мощным инструментом для преобразования текста в формате Markdown в HTML. Центральной частью процесса является работа с токенами. Токены — это структурированные объекты, представляющие отдельные элементы Markdown: заголовки, списки, ссылки, изображения, блоки кода и так далее.
Процесс преобразования можно разделить на два этапа:
marked.lexer).marked.Renderer).Метод marked.lexer принимает строку с Markdown и
возвращает массив токенов. Каждый токен имеет тип
(type) и набор свойств, зависящих от типа:
const marked = require('marked');
const markdown = `
# Заголовок 1
- Пункт списка
- Еще один пункт
`;
const tokens = marked.lexer(markdown);
console.log(tokens);
Пример токена для заголовка:
{
"type": "heading",
"depth": 1,
"text": "Заголовок 1"
}
Токен списка может выглядеть так:
{
"type": "list",
"ordered": false,
"items": [
{ "type": "list_item", "text": "Пункт списка" },
{ "type": "list_item", "text": "Еще один пункт" }
]
}
Каждый токен может содержать вложенные токены, например, списки внутри списков или параграфы внутри блоков цитаты.
После получения массива токенов их нужно превратить в HTML. Для этого используется рендерер:
const renderer = new marked.Renderer();
const html = marked.parser(tokens, { renderer });
console.log(html);
Метод marked.parser проходит по всем токенам и вызывает
соответствующие методы рендерера для каждого типа токена:
renderer.heading(text, level, raw) — генерирует HTML
для заголовка.renderer.paragraph(text) — для параграфа.renderer.list(body, ordered, start) — для списков.renderer.listitem(text) — для элемента списка.renderer.code(code, language, isEscaped) — для блока
кода.renderer.blockquote(quote) — для цитат.renderer.link(href, title, text) — для ссылок.renderer.image(href, title, text) — для
изображений.Каждый метод рендерера может быть переопределён для кастомного HTML. Например, можно изменить разметку заголовков или добавить классы для стилей:
const customRenderer = new marked.Renderer();
customRenderer.heading = (text, level) => {
return `<h${level} class="custom-heading">${text}</h${level}>`;
};
const customHtml = marked.parser(tokens, { renderer: customRenderer });
Токены могут быть вложенными. Например, элемент списка может содержать параграф и подсписок:
{
"type": "list_item",
"text": "Пункт с подсписком",
"tokens": [
{ "type": "paragraph", "text": "Подпункт текста" },
{
"type": "list",
"ordered": false,
"items": [
{ "type": "list_item", "text": "Вложенный пункт" }
]
}
]
}
При рендеринге вложенных токенов marked.parser
рекурсивно вызывает рендерер для всех внутренних токенов, что позволяет
получать корректный HTML для сложных структур Markdown.
Помимо изменения методов рендерера, библиотека Marked поддерживает следующие возможности:
Пример добавления класса к каждому параграфу:
const paragraphRenderer = new marked.Renderer();
paragraphRenderer.paragraph = text => {
return `<p class="custom-paragraph">${text}</p>`;
};
const htmlWithCustomParagraphs = marked.parser(tokens, { renderer: paragraphRenderer });
С версии Marked 5 поддерживается асинхронный рендеринг, что позволяет использовать промисы и обрабатывать асинхронные функции внутри рендерера. Для этого:
const asyncRenderer = new marked.Renderer();
asyncRenderer.code = async (code, language) => {
const highlighted = await highlightCodeAsync(code, language);
return `<pre><code>${highlighted}</code></pre>`;
};
const htmlAsync = await marked.parser(tokens, { renderer: asyncRenderer, async: true });
Асинхронный рендеринг особенно полезен при интеграции с внешними сервисами, например для подсветки синтаксиса кода или генерации динамического контента внутри Markdown.
marked.lexer перед
marked.parser, если требуется точечная обработка
токенов.{ async: true } в
marked.parser.Использование токенов предоставляет полный контроль над процессом преобразования Markdown в HTML и позволяет создавать как стандартные страницы, так и сложные кастомные разметки с расширенной функциональностью.