Подсветка синтаксиса

Библиотека Marked — это мощный инструмент для парсинга Markdown в JavaScript. Одним из ключевых аспектов, особенно при работе с кодом, является подсветка синтаксиса. В стандартной комплектации Marked преобразует текст в HTML, но не обеспечивает встроенной подсветки для блоков кода. Для этого используются интеграции с библиотеками подсветки, такими как highlight.js или Prism.js.


Настройка подсветки с использованием highlight.js

Чтобы подключить подсветку синтаксиса через highlight.js, необходимо выполнить несколько шагов:

  1. Установка библиотек:
npm install marked highlight.js
  1. Импорт в проект:
const marked = require('marked');
const hljs = require('highlight.js');
  1. Настройка рендерера Marked для подсветки:

Marked позволяет переопределять поведение рендерера с помощью объекта Renderer. Для блоков кода используется метод 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 `
${highlighted}
`; }; marked.setOptions({ renderer, gfm: true, breaks: true }); const markdown = ` \`\`\`javascript function sum(a, b) { return a + b; } \`\`\` `; const html = marked(markdown); console.log(html);

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

  • Проверка hljs.getLanguage(language) защищает от ошибок, если язык не поддерживается.
  • Добавление класса hljs обязательно для правильного применения стилей highlight.js.
  • При отсутствии указанного языка используется plaintext.

Настройка подсветки с использованием Prism.js

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

  1. Установка библиотек:
npm install marked prismjs
  1. Импорт и загрузка языковых модулей:
const marked = require('marked');
const Prism = require('prismjs');
require('prismjs/components/prism-javascript');
require('prismjs/components/prism-css');
  1. Настройка рендерера:
const renderer = new marked.Renderer();

renderer.code = (code, language) => {
  const validLanguage = Prism.languages[language] ? language : 'none';
  const highlighted = Prism.highlight(code, Prism.languages[validLanguage], validLanguage);
  return `
${highlighted}
`; }; marked.setOptions({ renderer }); const markdown = ` \`\`\`javascript console.log('Hello, Prism!'); \`\`\` `; const html = marked(markdown); console.log(html);

Отличительные моменты для Prism.js:

  • Класс language-${language} требуется для корректного применения стилей CSS Prism.
  • Prism поддерживает как браузерное, так и серверное окружение (Node.js).

Дополнительные параметры Marked для работы с кодом

  • langPrefix — префикс для классов блоков кода. По умолчанию 'language-'. Можно изменить:
marked.setOptions({
  langPrefix: 'hljs-'
});
  • highlight — функция для глобальной подсветки всех блоков кода без переопределения renderer.code:
marked.setOptions({
  highlight: function(code, lang) {
    const language = hljs.getLanguage(lang) ? lang : 'plaintext';
    return hljs.highlight(code, { language }).value;
  }
});
  • gfm и breaks — дополнительные параметры Markdown, влияющие на обработку текста, но не на подсветку.

Поддержка асинхронной подсветки

Некоторые библиотеки, такие как highlight.js с плагинами или веб-сборки Prism, поддерживают асинхронную загрузку языков. В таких случаях можно использовать асинхронный рендер:

async function renderMarkdown(markdown) {
  const renderer = new marked.Renderer();
  renderer.code = async (code, lang) => {
    const language = hljs.getLanguage(lang) ? lang : 'plaintext';
    const highlighted = await hljs.highlightAuto(code, [language]);
    return `
${highlighted.value}
`; }; marked.setOptions({ renderer }); return marked.parse(markdown); }

Асинхронный рендер полезен при динамической загрузке языковых модулей, минимизируя начальный вес бандла.


Структура HTML при подсветке

После обработки Markdown с подсветкой HTML-структура блока кода обычно выглядит так:


function sum(a, b) {
  return a + b;
}

Класс hljs или language-<язык> нужен для применения CSS-стилей подсветки. Без него код будет работать, но не будет визуально выделен.


Советы по производительности

  • Не использовать глобальный highlight.js для всех языков сразу — лучше подключать только нужные.
  • Для больших объемов Markdown применяйте precompiled или server-side rendering, чтобы не перегружать клиент.
  • Кэширование подсвеченного кода позволяет повторно использовать результат без повторного рендеринга.