Переопределение методов рендерера

Библиотека Marked предоставляет мощный инструмент для работы с Markdown в JavaScript, включая возможность кастомизации процесса рендеринга с помощью объекта Renderer. Это позволяет полностью контролировать, каким образом Markdown-теги преобразуются в HTML.

Основы объекта Renderer

По умолчанию Marked использует стандартный рендерер, который преобразует все элементы Markdown в соответствующий HTML. Однако, если необходимо изменить визуальное представление или добавить дополнительную обработку, создаётся собственный рендерер через new marked.Renderer():

const renderer = new marked.Renderer();

Каждый метод рендерера соответствует определённому Markdown-элементу: заголовкам, спискам, ссылкам, изображениям и т.д. Например, метод heading отвечает за заголовки:

renderer.heading = function (text, level, raw, slugger) {
    return `${text}`;
};

Ключевые параметры метода heading:

  • text — текст заголовка, уже обработанный Markdown.
  • level — уровень заголовка (1-6).
  • raw — исходный текст заголовка.
  • slugger — объект для генерации уникальных идентификаторов.

Переопределение методов для ссылок и изображений

Методы link и image позволяют управлять атрибутами HTML-тегов и .

renderer.link = function (href, title, text) {
    const safeHref = href.startsWith('http') ? href : '#';
    return `${text}`;
};

renderer.image = function (href, title, text) {
    return `${text}`;
};

Особенности переопределения ссылок:

  • Безопасность URL: проверка на допустимые протоколы (http, https).
  • Возможность добавлять атрибуты безопасности (rel="noopener noreferrer") и открытие в новом окне (target="_blank").

Для изображений можно автоматически задавать CSS-классы и fallback для атрибута title.

Кастомизация списков и элементов списка

Методы list и listitem дают полный контроль над визуальным оформлением списков:

renderer.list = function (body, ordered, start) {
    const tag = ordered ? 'ol' : 'ul';
    const startAttr = ordered && start !== 1 ? ` start="${start}"` : '';
    return `<${tag}${startAttr} class="custom-list">${body}`;
};

renderer.listitem = function (text) {
    return `
  • ${text}
  • `; };

    Особенности:

    • Поддержка нумерованных списков с нестандартного числа.
    • Возможность добавлять собственные CSS-классы.
    • Лёгкая интеграция с фреймворками или библиотеками для анимации элементов.

    Переопределение блоков кода

    Метод code отвечает за рендеринг блоков кода и может включать подсветку синтаксиса:

    renderer.code = function (code, language) {
        const validLang = language ? language : 'plaintext';
        return `
    ${code}
    `; };

    Преимущества:

    • Поддержка подсветки через внешние библиотеки (Prism.js, Highlight.js).
    • Гибкость для добавления кнопок «Скопировать код».
    • Автоматическое выставление класса языка для подсветки.

    Кастомизация параграфов и блоков цитат

    Методы paragraph и blockquote позволяют управлять структурой текста и цитат:

    renderer.paragraph = function (text) {
        return `

    ${text}

    `; }; renderer.blockquote = function (quote) { return `
    ${quote}
    `; };

    Особенности:

    • Возможность добавлять CSS-классы для типографики.
    • Поддержка вставки иконок, стилей и фреймов.

    Применение кастомного рендерера

    После переопределения нужных методов, объект рендерера передаётся в функцию marked:

    marked.use({ renderer });
    
    const html = marked.parse(markdownText);

    Преимущество использования marked.use — возможность комбинировать кастомные рендереры с различными настройками Markdown, включая gfm, breaks, smartLists.

    Советы по разработке собственных методов

    • Всегда проверять входные данные для безопасности (особенно ссылки и HTML-теги).
    • Сохранять базовое поведение метода, если нужна частичная кастомизация. Например:
    const originalRenderer = new marked.Renderer();
    renderer.heading = function (text, level, raw, slugger) {
        const baseHtml = originalRenderer.heading(text, level, raw, slugger);
        return `
    ${baseHtml}
    `; };
    • Использовать CSS-классы вместо инлайновых стилей для лучшей поддержки и масштабируемости.
    • В сложных сценариях комбинировать несколько методов рендерера для комплексной обработки элементов Markdown.