Интеграция с Prism

Для подсветки синтаксиса кода в Markdown с помощью библиотеки Marked часто используется интеграция с библиотекой Prism. Prism предоставляет готовые темы и поддержку множества языков программирования, что позволяет легко стилизовать блоки кода.

Основная идея интеграции заключается в переопределении функции рендеринга блоков кода (renderer.code) в Marked, чтобы она использовала Prism для подсветки.

import { marked } from 'marked';
import Prism from 'prismjs';

// Подключение языков по необходимости
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-html';

// Настройка рендерера
const renderer = new marked.Renderer();

renderer.code = (code, language) => {
  const validLang = Prism.languages[language] ? language : 'markup';
  const highlighted = Prism.highlight(code, Prism.languages[validLang], validLang);
  return `<pre class="language-${validLang}"><code class="language-${validLang}">${highlighted}</code></pre>`;
};

marked.setOptions({
  renderer,
  gfm: true,
  breaks: true,
});

Выбор языка для подсветки

Prism поддерживает большое количество языков, но для корректной работы необходимо убедиться, что соответствующие компоненты подключены. Если язык не подключен или не распознан, рекомендуется использовать markup (HTML) как язык по умолчанию.

const validLang = Prism.languages[language] ? language : 'markup';

Это предотвращает ошибки и сохраняет корректное форматирование блока кода.

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

Prism поставляется с набором CSS-тем. Для отображения подсветки нужно подключить одну из тем:

<link rel="stylesheet" href="prism.css">

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

Поддержка кастомных языков

Для специфичных языков, не включённых в стандартный пакет Prism, можно подключать отдельные компоненты:

import 'prismjs/components/prism-python';
import 'prismjs/components/prism-ruby';

Это позволяет расширять функциональность подсветки без изменения кода Marked.

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

При рендеринге Markdown, полученного динамически (например, с сервера), важно применять marked() и сразу передавать результат в DOM. Prism подсветит код только после того, как HTML уже вставлен в документ:

const markdown = `
\`\`\`javascript
console.log("Hello, world!");
\`\`\`
`;

const container = document.getElementById('content');
container.innerHTML = marked(markdown);

Блок кода будет обернут в pre и code с классом language-javascript, и Prism применит стили подсветки.

Оптимизация производительности

При больших объемах Markdown или множестве блоков кода может быть полезно:

  • Подключать только необходимые языки Prism.
  • Использовать ленивую подсветку или выполнение Prism только после вставки контента.
  • Кэшировать результаты подсветки для повторяющихся блоков.
const cache = new Map();

renderer.code = (code, language) => {
  const key = language + code;
  if (cache.has(key)) return cache.get(key);

  const validLang = Prism.languages[language] ? language : 'markup';
  const highlighted = Prism.highlight(code, Prism.languages[validLang], validLang);
  const result = `<pre class="language-${validLang}"><code class="language-${validLang}">${highlighted}</code></pre>`;
  
  cache.set(key, result);
  return result;
};

Поддержка расширений Markdown

Marked позволяет использовать расширенные синтаксические возможности Markdown, такие как таблицы, списки и ссылки. Prism не влияет на их работу, но важно учитывать, что подсветка применяется только к блокам кода.

# Пример таблицы

| Язык | Код |
|------|-----|
| JS   | console.log('test'); |

При рендеринге с Marked таблицы и текст будут форматироваться стандартными средствами, а блоки кода внутри таблиц также могут подсвечиваться при правильном указании language.

Интеграция с веб-фреймворками

При использовании Marked и Prism в React, Vue или других фреймворках:

  • Преобразование Markdown в HTML лучше делать в методах жизненного цикла (componentDidMount / onMounted), чтобы DOM был готов.
  • Для React рекомендуется использовать dangerouslySetInnerHTML, при этом необходимо тщательно фильтровать ввод, чтобы предотвратить XSS.
<div dangerouslySetInnerHTML={{ __html: marked(markdown) }} />
  • Prism автоматически применит стили к блокам кода после рендеринга.

Ключевые моменты интеграции

  • Рендерер Marked можно полностью кастомизировать под Prism.
  • Всегда проверять наличие языка в Prism, чтобы избежать ошибок.
  • Подключение CSS темы Prism обязательно для визуальной подсветки.
  • Для производительности подключать только нужные языки и кэшировать результаты.
  • Интеграция с фреймворками требует правильного момента вставки HTML в DOM.

Эта связка Marked + Prism позволяет создавать красивый, читаемый и наглядный Markdown-контент с подсветкой кода любого объема и сложности.