Библиотека Marked является одной из самых популярных для работы с Markdown в JavaScript. Она позволяет преобразовывать текст в формате Markdown в HTML, предоставляя при этом гибкие возможности для кастомизации рендеринга отдельных элементов. Особое внимание уделяется блокам кода, которые часто требуют специфической обработки, например, для подсветки синтаксиса.
В Markdown блок кода задается двумя способами:
`console.log('Hello, world!')`
```javascript
function sum(a, b) {
return a + b;
}
Для рендеринга **многострочных блоков кода** Marked предоставляет отдельный метод `renderer.code`.
---
#### Кастомизация рендерера
Marked использует объект `Renderer`, позволяющий переопределять поведение отдельных элементов Markdown. Для блоков кода используется метод:
```javascript
const { marked } = require('marked');
const renderer = new marked.Renderer();
renderer.code = (code, language, isEscaped) => {
const langClass = language ? ` class="language-${language}"` : '';
return `<pre><code${langClass}>${isEscaped ? code : escapeHtml(code)}</code></pre>`;
};
marked.setOptions({ renderer });
Пояснения по параметрам:
code — текст блока кода.language — язык программирования, если он указан после
тройных апострофов.isEscaped — флаг, указывающий, была ли строка уже
экранирована.Метод escapeHtml необходим для безопасного
преобразования специальных HTML-символов (<,
>, &) в соответствующие сущности.
Чтобы блоки кода выглядели более наглядно, часто используют подсветку синтаксиса. Популярной библиотекой для этого является highlight.js:
const hljs = require('highlight.js');
renderer.code = (code, language) => {
const validLang = hljs.getLanguage(language) ? language : 'plaintext';
const highlighted = hljs.highlight(code, { language: validLang }).value;
return `<pre><code class="hljs language-${validLang}">${highlighted}</code></pre>`;
};
Особенности реализации:
hljs.getLanguage(language) предотвращает
ошибки при неизвестных языках.hljs.highlight возвращает HTML с уже добавленными
CSS-классами для подсветки.hljs позволяет применить стандартные
стили highlight.js.В некоторых случаях блоки кода могут требовать асинхронной обработки,
например, запрос подсветки с внешнего сервиса или вычисление
содержимого. Marked поддерживает асинхронный рендеринг
через функцию marked.parse с опцией
async: true:
const markedAsync = async (markdownText) => {
return await marked.parse(markdownText, {
renderer,
async: true
});
};
В сочетании с асинхронными библиотеками подсветки кода это позволяет выполнять вычисления и возвращать результат без блокировки основного потока.
Для расширенного контроля можно добавлять
data-атрибуты, id или title к
блокам кода:
renderer.code = (code, language) => {
const langClass = language ? `language-${language}` : '';
return `<pre data-language="${language || 'none'}"><code class="${langClass}">${escapeHtml(code)}</code></pre>`;
};
Это открывает возможность интеграции с фронтенд-виджетами, например, редакторами кода или кнопками копирования.
const { marked } = require('marked');
const hljs = require('highlight.js');
const renderer = new marked.Renderer();
renderer.code = (code, language) => {
const lang = hljs.getLanguage(language) ? language : 'plaintext';
const highlightedCode = hljs.highlight(code, { language: lang }).value;
return `<pre><code class="hljs language-${lang}">${highlightedCode}</code></pre>`;
};
marked.setOptions({
renderer,
gfm: true,
breaks: true,
smartLists: true,
smartypants: true
});
const markdownText = `
\`\`\`javascript
console.log('Marked + Highlight.js');
\`\`\`
`;
const html = marked(markdownText);
console.log(html);
<, > и &.language-<lang> и hljs упрощает
стилизацию через CSS.Использование renderer.code в Marked открывает полный
контроль над тем, как блоки кода будут отображаться, сочетая
безопасность, подсветку синтаксиса и гибкость кастомизации под любые
требования.