Работа с синхронным API

Библиотека Marked в JavaScript предоставляет инструменты для парсинга Markdown и генерации HTML. Синхронный API позволяет преобразовывать строки Markdown в HTML без необходимости работы с асинхронными функциями или промисами. Это особенно удобно при обработке локальных данных или при необходимости немедленного получения результата.

import { marked } from 'marked';

const markdownString = `
# Заголовок первого уровня
Пример **жирного текста** и *курсива*.
`;

const html = marked.parse(markdownString);
console.log(html);

В данном примере метод marked.parse синхронно возвращает HTML. Обработка Markdown выполняется моментально, без отложенных операций.


Настройка параметров синхронного рендеринга

Marked предоставляет объект options, с помощью которого можно детально настроить процесс парсинга. Основные параметры:

  • gfm – использование расширенного синтаксиса GitHub Markdown (true по умолчанию).
  • breaks – превращает переносы строк в
    при значении true.
  • smartLists – улучшенные списки с вложенностью (true/false).
  • headerIds – автоматическая генерация идентификаторов для заголовков (true/false).
  • mangle – защита email-ссылок от спам-ботов.

Пример использования:

marked.setOptions({
  gfm: true,
  breaks: false,
  smartLists: true,
  headerIds: true,
  mangle: false
});

const html = marked.parse("# Заголовок с настройками");

Эти опции влияют только на синхронное выполнение метода parse, обеспечивая гибкость и предсказуемость результата.


Создание собственного рендерера

Для детального контроля над HTML можно создать пользовательский рендерер. Класс Renderer позволяет переопределять поведение для отдельных элементов Markdown.

const renderer = {
  heading(text, level) {
    return `${text}`;
  },
  link(href, title, text) {
    return `${text}`;
  }
};

marked.use({ renderer });

const html = marked.parse("# Заголовок с кастомным рендерером");

Использование собственного рендерера особенно полезно для генерации HTML с кастомными классами, атрибутами и безопасными ссылками.


Обработка инлайн и блочных элементов

Синхронный API предоставляет полный контроль над инлайн- и блочными токенами:

  • Инлайн-токены: ссылки, изображения, жирный текст, курсив, код в строке.
  • Блочные токены: заголовки, списки, цитаты, кодовые блоки, таблицы.

Можно парсить Markdown до токенов и затем рендерить их вручную:

const tokens = marked.lexer(markdownString);

tokens.forEach(token => {
  if (token.type === 'heading') {
    console.log(`Заголовок: ${token.text}, уровень: ${token.depth}`);
  }
});

Метод lexer возвращает массив токенов, что открывает возможности для анализа структуры документа перед генерацией HTML.


Использование кастомных токенов

Для расширения функционала можно добавлять собственные типы токенов:

marked.use({
  extensions: [
    {
      name: 'highlight',
      level: 'inline',
      start(src) { return src.indexOf('=='); },
      tokenizer(src) {
        const match = /^==(.+?)==/.exec(src);
        if (match) return { type: 'highlight', raw: match[0], text: match[1] };
      },
      renderer(token) {
        return `${token.text}`;
      }
    }
  ]
});

const html = marked.parse("Это ==важное== слово.");

Такой подход позволяет добавлять произвольные синтаксические конструкции и сразу обрабатывать их в синхронном режиме.


Производительность и особенности

Синхронный API Marked оптимизирован для работы с большими объемами Markdown:

  • Парсинг выполняется в памяти без асинхронной задержки.
  • Генерация HTML происходит в одну проходку, без промежуточных операций.
  • Поддерживаются все стандартные элементы Markdown и GitHub Flavored Markdown.

Для больших документов рекомендуется использовать токенизацию перед рендерингом, чтобы управлять памятью и адаптировать вывод под специфические нужды.


Безопасность и фильтрация

При использовании синхронного рендеринга важно учитывать XSS-уязвимости:

  • Опция sanitize ранее использовалась для фильтрации HTML, но устарела.
  • Рекомендуется обрабатывать HTML через сторонние библиотеки, например, DOMPurify, после генерации HTML:
import DOMPurify from 'dompurify';

const dirtyHtml = marked.parse(markdownString);
const cleanHtml = DOMPurify.sanitize(dirtyHtml);

Это обеспечивает безопасность без потери синхронности работы Marked.