Marked — это мощная библиотека для парсинга Markdown в JavaScript, которая позволяет преобразовывать текст с разметкой Markdown в HTML. В основе её работы лежит система лексического анализа, где Markdown-текст сначала разбивается на токены, а затем каждый токен преобразуется в соответствующий HTML-элемент.
Токенайзер — это компонент, отвечающий за разделение исходного текста на отдельные токены. Токены представляют собой логические блоки Markdown: заголовки, списки, параграфы, ссылки, изображения, цитаты, коды и пр. В Marked существует несколько уровней токенизации: базовая (inline) и блочная (block), каждая из которых имеет свои особенности.
Блочный токенайзер отвечает за обработку больших структурных элементов документа. Примеры блочных токенов:
heading — заголовки, например
# Заголовок 1paragraph — обычный текстовый абзацlist — нумерованные и маркированные спискиblockquote — блоки цитатcode — блоки кода с поддержкой языкаhr — горизонтальные линииПринцип работы:
Пример структуры токена заголовка:
{
type: 'heading',
depth: 2,
text: 'Пример заголовка'
}
Inline-токенизация обрабатывает внутреннее содержание блочных элементов, например выделение текста, ссылки и изображения. Основные inline-токены:
em и strong — курсив и жирный текстlink — гиперссылкиimage — изображенияcodespan — встроенный кодdel — зачёркнутый текстInline-токенайзер работает рекурсивно: он получает текст блочного токена и ищет последовательности Markdown-разметки, создавая вложенные токены.
Пример токена для ссылки:
{
type: 'link',
href: 'https://example.com',
title: 'Описание ссылки',
text: 'Перейти на сайт'
}
Marked предоставляет возможность пользовательской настройки
токенайзеров через объект Tokenizer. Это
позволяет:
Пример создания кастомного токенайзера для обработки выделения текста двойными кавычками:
const { marked } = require('marked');
class CustomTokenizer extends marked.Tokenizer {
strong(src) {
const match = /^""(.+?)""/.exec(src);
if (match) {
return {
type: 'strong',
raw: match[0],
text: match[1]
};
}
return super.strong(src);
}
}
marked.use({ tokenizer: new CustomTokenizer() });
В этом примере стандартное выделение жирным через
**текст** остаётся доступным, но добавляется новая
возможность: ""текст"" также распознаётся как жирный
текст.
Тестирование токенайзеров критически важно для проверки корректности разбора Markdown и предотвращения ошибок в последующем рендеринге.
Юнит-тесты на отдельные токены Для каждого типа токена создаются тестовые строки, проверяется правильность распознавания и формирование объекта токена.
Пример теста для заголовка:
const tokenizer = new marked.Tokenizer();
const token = tokenizer.heading('# Заголовок');
console.assert(token.type === 'heading', 'Неверный тип токена');
console.assert(token.depth === 1, 'Неверная глубина заголовка');
console.assert(token.text === 'Заголовок', 'Неверный текст заголовка');Тесты на inline-токены Inline-токены часто тестируются с рекурсивными комбинациями, например, текст с ссылкой внутри жирного текста.
const token = tokenizer.strong('**[Ссылка](https://example.com)**');
console.assert(token.type === 'strong', 'Ожидался strong');
console.assert(token.tokens[0].type === 'link', 'Внутри должен быть link');Интеграционные тесты Проверка полного парсинга Markdown-документа с различными уровнями вложенности. Тест фиксирует соответствие структуры токенов ожидаемой схеме.
Система токенов в Marked — это гибкая и мощная основа для разбора Markdown. Качественное тестирование обеспечивает:
Тщательная настройка и проверка токенайзеров позволяет создавать надёжные и масштабируемые Markdown-приложения.