Marked — это высокопроизводительная библиотека для преобразования Markdown в HTML. Помимо простого конвертера, она предоставляет расширенные возможности работы с внутренней структурой документа через дерево токенов. Токены представляют собой промежуточное представление Markdown-документа в виде структурированных объектов, что позволяет производить сложные трансформации содержимого до генерации HTML.
В Marked процесс обработки Markdown делится на несколько этапов:
Каждый токен — это объект JavaScript, имеющий обязательное поле
type, определяющее тип элемента, и дополнительные поля в
зависимости от типа. Например:
{
type: 'heading',
depth: 2,
text: 'Пример заголовка'
}
Типичные поля токена:
type — строка с типом элемента (paragraph,
heading, list, list_item,
code и т.д.).text — текстовое содержимое токена (для заголовков,
параграфов).tokens — массив дочерних токенов (например, для списков
или вложенных элементов).depth — глубина заголовка (1-6 для
h1–h6).lang — язык программирования для токена
code.Метод Lexer.lex() используется для преобразования
Markdown-текста в массив токенов:
import { Lexer } from 'marked';
const markdown = `
# Заголовок 1
- Пункт 1
- Пункт 2
`;
const tokens = Lexer.lex(markdown);
console.log(tokens);
Вывод будет содержать токены типа heading и
list, где каждый пункт списка представлен отдельным токеном
list_item.
Для более сложных документов структура токенов становится
иерархической, где некоторые токены содержат вложенные
массивы tokens.
Трансформация дерева токенов позволяет:
import { Lexer, Parser } from 'marked';
const tokens = Lexer.lex(markdown);
tokens.forEach(token => {
if (token.type === 'heading' && token.depth < 6) {
token.depth += 1;
}
});
const html = Parser.parse(tokens);
Здесь Parser.parse() принимает массив токенов и
превращает их в HTML с учетом внесенных изменений.
Для сложных вложенных структур (списки, блоки кода, цитаты) необходимо использовать рекурсивный обход:
function transformTokens(tokens) {
tokens.forEach(token => {
if (token.type === 'paragraph') {
token.text = token.text.toUpperCase();
}
if (token.tokens) {
transformTokens(token.tokens);
}
});
}
transformTokens(tokens);
Такой подход позволяет изменять любую часть Markdown-документа, сохраняя его вложенность.
Marked поддерживает добавление собственных типов токенов для
специфических целей. Для этого используется объект
Lexer.rules и методы расширения. Например, можно добавить
токен для блоков с предупреждением:
Lexer.rules.block.warning = /^!!!\s*(.+)$/m;
function customLexer(src) {
let tokens = Lexer.lex(src);
tokens.forEach(token => {
if (token.type === 'warning') {
token.html = `<div class="warning">${token.text}</div>`;
}
});
return tokens;
}
Для более тонкой настройки рендеринга используют
Renderer:
import { Renderer, Parser } from 'marked';
const renderer = new Renderer();
renderer.heading = (text, level) => `<h${level} class="custom">${text}</h${level}>`;
const html = Parser.parse(tokens, { renderer });
Комбинация кастомного рендерера и модифицированного дерева токенов обеспечивает полный контроль над конечным HTML.
tokens,
depth, text), чтобы избежать ошибок при
рендеринге.Дерево токенов Marked является мощным инструментом для промежуточной обработки Markdown. Оно открывает возможности для глубоких трансформаций документа, позволяя:
Эта архитектура делает Marked не только быстрым конвертером, но и гибкой платформой для построения сложных Markdown-приложений.