Интеграция с highlight.js

Для начала необходимо установить библиотеки marked и highlight.js через npm или yarn:

npm install marked highlight.js

или

yarn add marked highlight.js

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

import { marked } from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css'; // Подключение темы для подсветки

Настройка renderer для подсветки кода

Библиотека marked позволяет кастомизировать процесс рендеринга через объект renderer. Для интеграции с highlight.js нужно переопределить метод code:

const renderer = new marked.Renderer();

renderer.code = (code, language) => {
  const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
  const highlighted = hljs.highlight(code, { language: validLanguage }).value;
  return `<pre><code class="hljs ${validLanguage}">${highlighted}</code></pre>`;
};

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

Ключевые моменты:

  • Проверка языка через hljs.getLanguage(language) предотвращает ошибки при неизвестных языках.
  • Поддержка параметров GFM (gfm: true) и переносов строк (breaks: true) обеспечивает соответствие современному Markdown-стандарту.

Рендеринг Markdown с подсветкой

После настройки renderer можно преобразовать Markdown-текст в HTML с подсветкой:

const markdownText = `
# Пример кода

\`\`\`javascript
function hello(name) {
  console.log('Привет, ' + name);
}
hello('Мир');
\`\`\`
`;

const html = marked(markdownText);

document.getElementById('content').innerHTML = html;
  • marked(markdownText) возвращает HTML-строку с уже подсвеченным кодом.
  • Элемент с id content будет содержать HTML, который можно стилизовать с помощью CSS темы highlight.js.

Использование асинхронной подсветки

Для больших блоков кода можно применять асинхронную версию highlight.js, чтобы не блокировать UI:

renderer.code = async (code, language) => {
  const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
  const result = await hljs.highlight(code, { language: validLanguage });
  return `<pre><code class="hljs ${validLanguage}">${result.value}</code></pre>`;
};

async function renderMarkdown(markdownText) {
  const html = await marked.parse(markdownText, { renderer });
  document.getElementById('content').innerHTML = html;
}
  • marked.parse поддерживает асинхронный рендеринг с промисами.
  • Асинхронная подсветка улучшает отзывчивость интерфейса при больших документах.

Настройка темы и стилей

highlight.js поставляется с множеством готовых тем. Для их применения достаточно импортировать соответствующий CSS-файл:

import 'highlight.js/styles/atom-one-dark.css';

Для динамического изменения темы можно менять классы hljs на уровне <pre> или <code> или загружать другой CSS-файл через JS.

Добавление поддержки пользовательских языков

В стандартной сборке highlight.js не всегда есть все языки. Для добавления нового языка нужно его импортировать:

import javascript from 'highlight.js/lib/languages/javascript';
hljs.registerLanguage('javascript', javascript);
  • Поддержка только необходимых языков уменьшает размер сборки.
  • Можно подключать несколько языков и использовать их в Markdown без ошибок подсветки.

Дополнительные настройки marked

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

  • headerIds: true — генерация уникальных id для заголовков.
  • mangle: false — отключение автоматического экранирования email-адресов.
  • sanitize: false — отключение удаления HTML-тегов (важно при вставке кода с HTML внутри).

Пример полной конфигурации:

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

Рекомендации по безопасности и производительности

  • Всегда проверять Markdown на потенциально опасный HTML или скрипты перед вставкой в DOM.
  • Для больших документов использовать asynchronous highlighting, чтобы не блокировать основной поток.
  • Минимизировать количество одновременно подключаемых языков в highlight.js, чтобы уменьшить размер бандла.

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