Docusaurus Prerender Mermaid Плагин: статичные и доступные диаграммы
Информация о статье

Автор: Дмитрий Дугарев
Плагин для Docusaurus, который выполняет предварительный рендеринг ваших Mermaid-диаграмм в статические изображения SVG или PNG во время сборки.
Это решает распространенные проблемы с рендерингом Mermaid на стороне клиента, такие как низкая производительность, смещение макета содержимого (CLS) и, в особенности, проблемы с доступностью и SEO, вызванные отсутствием alt текста, подписей, текстовых описаний и плохой семантической структурой HTML.
Демо-пример
Вот как бы вы написали диаграмму в вашем файле .md или .mdx:
- Код Mermaid
- Сгенерированный HTML
- Сгенерированная диаграмма
Используйте мета-поля в блоке, похожем на frontmatter, чтобы добавить id, alt текст, caption (подпись) и aria-describedby для доступности.
```mermaid
---
id: company-flow
alt: Блок-схема, показывающая процесс компании.
caption: Официальный процесс разработки в компании.
width: 300px
descriptionId: company-flow-desc
date: 2025-11-03T16:00:00+01:00
---
graph TD
A[Sales] --> B(Development);
B --> C{Testing};
C --> D[Deployment];
```
Так выглядит приведенный выше код Mermaid, преобразованный в HTML во время сборки, если у вас включены обе темы (светлая и темная):
<figure id="company-flow" class="static-mermaid-figure">
<!-- Этого <img> не будет на странице, если в конфигурации включена только темная тема -->
<img
width="500px"
class="mermaid-light"
src="/img/diagrams/company-flow-ru-light.svg"
alt="Блок-схема, показывающая процесс компании."
aria-labelledby="company-flow-caption"
aria-describedby="company-flow-desc"
/>
<!-- Этого <img> не будет на странице, если в конфигурации включена только светлая тема -->
<img
width="500px"
class="mermaid-dark"
src="/img/diagrams/company-flow-ru-dark.svg"
alt="Блок-схема, показывающая процесс компании."
aria-labelledby="company-flow-caption"
aria-describedby="company-flow-desc"
/>
<figcaption id="company-flow-caption">
Официальный процесс разработки в компании.
</figcaption>
</figure>
В зависимости от вашей конфигурации будет сгенерирован только <img> для светлой или темной темы, или оба, если включен переключатель тем.
При переключении тем Docusaurus автоматически показывает правильное изображение и скрывает другое без какого-либо JavaScript — это происходит мгновенно через CSS.
Поскольку скрытое изображение имеет display: none, оно удаляется из дерева доступности и игнорируется программами чтения с экрана, поэтому читается только видимое изображение.
Вот как выглядит сгенерированная диаграмма на сайте:
Описание диаграммы процесса компании.
Эта диаграмма иллюстрирует основные этапы процесса нашей компании, начиная с Продаж, переходя к Разработке, затем к Тестированию и завершаясь Развертыванием.
Руководство по стилизации
Диаграммы поставляются без каких-либо стилей по умолчанию, поэтому вы можете стилизовать их в соответствии с дизайном вашего сайта.
.static-mermaid-figure: Основная обертка<figure>..mermaid-light: Тег<img>для светлой темы..mermaid-dark: Тег<img>для темной темы.figcaption: Элемент подписи.
Пример стилизации SCSS
Вот расширенный пример (с использованием SCSS) для добавления фона, border-radius и пользовательских нумерованных счетчиков к вашим figures.
.static-mermaid-figure {
// Добавить счетчик для каждого figure
counter-increment: figurecounter;
margin: 2rem 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem; // Пробел между изображением и подписью
// Стилизация тегов img
& > img {
max-width: 100%;
max-height: 100%;
padding: 1.5rem;
background-color: var(--ifm-card-background-color);
border-radius: 0.75rem;
border: 1px solid var(--ifm-color-emphasis-300);
}
// Стилизация подписи
& > figcaption {
margin-top: 0.25rem;
font-size: 0.9rem;
color: var(--ifm-font-color-secondary);
font-style: italic;
text-align: center;
// Пример пользовательского счетчика "Рисунок 1.1: "
&::before {
content: 'Рисунок ' counter(h2counter) '.' counter(figurecounter) ': ';
font-weight: 600;
color: var(--ifm-font-color-base);
font-style: normal;
}
}
}
Что это и зачем?
По умолчанию Docusaurus и @docusaurus/theme-mermaid отображают диаграммы на стороне клиента. Это означает, что браузер каждого посетителя должен запустить библиотеку Mermaid.js, чтобы проанализировать текст вашей диаграммы и превратить его в изображение.
У этого подхода есть несколько проблем:
- Низкая производительность: Это добавляет дополнительный JavaScript на ваш сайт, увеличивая время загрузки.
- Смещение макета (Layout Shift): Появляется "вспышка" нестилизованного кода перед отображением диаграммы, что заставляет содержимое вашей страницы "прыгать" (плохой показатель Core Web Vital).
- Отсутствие статического экспорта: Диаграммы не отображаются в RSS-каналах, предварительных просмотрах в социальных сетях и других средах без JavaScript.
- Проблемы с доступностью: Рендерер на стороне клиента не добавляет
altтекст или подписи, делая диаграммы недоступными для программ чтения с экрана. Он также не использует семантические элементы HTML, такие как<figure>и<figcaption>, и невозможно сослаться на внешние текстовые описания с помощьюaria-describedby. - Проблемы с SEO: Поисковые системы не могут индексировать содержимое ваших диаграмм, что потенциально вредит вашему SEO.
Этот плагин исправляет все это, выполняя рендеринг один раз во время сборки (npm run build). Он генерирует статические теги <img>, что обеспечивает молниеносную работу без смещения макета для ваших пользователей. Для доступности он оборачивает каждую диаграмму в соответствующий тег <figure> и поддерживает подписи в <figcaption>, alt текст и aria-describedby для текстовых описаний.
Возможности
- Статический рендеринг: Преобразует блоки
mermaidв статические теги<img>. - Поддержка темного/светлого режима: Автоматически отображает светлую и темную версии ваших диаграмм на основе настроек вашей темы Docusaurus.
- Доступность: Генерирует HTML-обертку
<figure>с<img>и<figcaption>для программ чтения с экрана, заполняяaltтекст, подпись иaria-describedby, используя метаданные вашей диаграммы. - Поддержка метаданных: Используйте блок, похожий на frontmatter, внутри вашей диаграммы, чтобы добавить
id,altтекст,caption(подпись) и ссылку на текстовое описание черезaria-describedby. - Полностью настраиваемый: Интегрируется непосредственно с вашим
docusaurus.config.ts, включаяthemeConfig.mermaid. - Кэширование: Уже отображенные диаграммы пропускаются, что ускоряет последующие сборки.
- Настраиваемый вывод: Выбирайте между форматами SVG и PNG, устанавливайте каталоги вывода и передавайте пользовательские аргументы в Mermaid CLI.
- Управление параллелизмом: Настройте, сколько диаграмм отображать параллельно для оптимальной производительности сборки.
Как это работает
Плагин работает в три этапа:
Текстовое описание диаграммы "Обзор рабочего процесса Docusaurus Prerender
Mermaid Plugin."
Эта блок-схема иллюстрирует три основных этапа рабочего процесса Docusaurus Prerender Mermaid Plugin:
-
Время сборки (Основной плагин):
- Сканирует ваши каталоги с контентом (
docs,blogи т. д.) на наличие всех блоковmermaid. - Читает ваш
docusaurus.config.ts, чтобы найти названия вашей светлой и темной темы для Mermaid. Если у вас есть файлmermaid.config.json, он использует настройки оттуда вместоdocusaurus.config.ts. - Если переключение цветового режима отключено через
themeConfig.mermaid.disableColorMode, он отображает только одну тему по умолчанию, определенную вthemeConfig.colorMode.defaultMode. - Он вызывает
@mermaid-js/mermaid-cli(mmdc) для рендеринга двух изображений для каждой диаграммы (например,diagram-ru-light.svgиdiagram-ru-dark.svg), если переключение тем включено, или только одного изображения, если отключено. - Он сохраняет эти изображения в каталог
static/img/diagrams(или ваш настроенныйoutputDir). - Кэширует отображенные диаграммы для ускорения будущих сборок.
- Когда Docusaurus запускает процесс сборки, он автоматически копирует эти изображения из
static/в конечный каталогbuild/.
- Сканирует ваши каталоги с контентом (
-
Преобразование контента (Плагин Remark):
- Во время преобразования Markdown в HTML плагин remark перехватывает блок
mermaid. - Он заменяет блок кода структурой HTML
<figure>. - Внутрь figure он вставляет два тега
<img>, указывающие на статические файлы (или один, если переключение тем отключено). - Диаграммы с
prerender: falseпропускаются и остаются как есть для рендеринга на стороне клиента. - Он заполняет атрибуты доступности, такие как
alt,aria-labelиaria-describedby, используя метаданные, предоставленные в блоке диаграммы. - Если предоставлена подпись (
caption), он добавляет элемент<figcaption>под изображениями. - В режиме разработки (
npm run start) он показывает оригинальный рендерер Mermaid для живого предварительного просмотра и более быстрых правок, который модифицируется с той же структурой, что и статический вывод, используя<figure>,<img>и<figcaption>, чтобы максимально соответствовать выводу сборки.
- Во время преобразования Markdown в HTML плагин remark перехватывает блок
-
Клиентская сторона (Браузер):
- Плагин внедряет крошечный CSS-файл, который использует атрибут Docusaurus
[data-theme='dark']для показа правильного<img>и скрытия другого. Это переключение происходит мгновенно и не требует JavaScript.
- Плагин внедряет крошечный CSS-файл, который использует атрибут Docusaurus
Установка и настройка
Вам необходимо установить плагин из реестра npm:
npm install @barrierenlos/docusaurus-prerender-mermaid
Вы должны добавить плагин в два места в вашем docusaurus.config.ts:
- Основной плагин в корневой массив
plugins. - Плагин remark в опции вашего пресета docs/blog/pages.
import type { Config } from '@docusaurus/types';
// 1. Импортируйте плагин remark
import remarkMermaidStatic from '@barrierenlos/docusaurus-prerender-mermaid/remark';
const config: Config = {
// ...
i18n: {
defaultLocale: 'ru',
locales: ['de', 'en', 'ru'],
},
themeConfig: {
// ...
// Плагин читает эту конфигурацию автоматически!
mermaid: {
theme: { light: 'neutral', dark: 'dark' },
options: {
fontFamily: 'Arial, sans-serif',
},
},
},
// 2. Добавьте основной плагин
plugins: [
[
'@barrierenlos/docusaurus-prerender-mermaid',
{
// Опции плагина...
contentPaths: ['docs', 'legal'], // Каталоги для сканирования
outputDir: 'static/img/diagrams', // Куда записывать SVG
outputFormat: 'svg', // 'svg' или 'png'
// concurrency: 4, // Сколько рендерить одновременно. По умолчанию - кол-во CPU
mmdcArgs: ['-b', 'transparent'], // Дополнительные аргументы mmdc
// другие опции...
},
],
// ... другие плагины
],
presets: [
[
'classic',
{
docs: {
// 3. Добавьте плагин remark
beforeDefaultRemarkPlugins: [remarkMermaidStatic],
// ... другие опции docs
},
blog: {
// 3. Добавьте плагин remark (если вы используете mermaid в блоге)
beforeDefaultRemarkPlugins: [remarkMermaidStatic],
// ... другие опции blog
},
// ...
} satisfies Preset.Options,
],
],
};
export default config;
Параметры конфигурации
Все параметры являются необязательными и передаются основному плагину в docusaurus.config.ts.
| Опция | Описание | По умолчанию |
|---|---|---|
contentPaths | Массив каталогов контента для сканирования диаграмм, относительно siteDir. | ['docs', 'blog'] |
outputDir | Каталог для вывода отображенных изображений, относительно каталога static. | 'img/diagrams' |
outputFormat | Формат вывода. Может быть 'svg' или 'png'. | 'svg' |
configFile | Путь к физическому файлу mermaid.config.json. Если указан, он переопределяет themeConfig.mermaid.config для базовых стилей. | 'mermaid.config.json' |
concurrency | Количество диаграмм для одновременного рендеринга. | os.cpus().length |
mmdcArgs | Массив дополнительных строковых аргументов для передачи в mmdc CLI. | ['-b', 'transparent'] |
outputSuffixes | Суффиксы, добавляемые для светлой и темной тем. | { light: '-light', dark: '-dark' } |
Примеры конфигурации
Конфигурация по умолчанию (минимальная)
Если вас устраивают все значения по умолчанию, вам просто нужно зарегистрировать плагин. Плагину remark опции не нужны.
import remarkMermaidStatic from 'docusaurus-prerender-mermaid/remark';
const config: Config = {
// ...
plugins: [
'docusaurus-prerender-mermaid',
// ...
[
'@docusaurus/plugin-content-docs',
{
id: 'your-custom-id',
path: 'your-custom-path',
// ...
beforeDefaultRemarkPlugins: [remarkMermaidStatic],
},
],
],
presets: [
[
'classic',
{
docs: {
beforeDefaultRemarkPlugins: [remarkMermaidStatic],
// ...
},
// ...
},
],
],
};
Расширенная (полная) конфигурация
Этот пример изменяет каталоги контента, путь вывода и добавляет пользовательский коэффициент масштабирования в mmdc.
import remarkMermaidStatic from 'docusaurus-prerender-mermaid/remark';
const config: Config = {
// ...
plugins: [
[
'docusaurus-prerender-mermaid',
{
contentPaths: ['docs', 'legal', 'src/pages'],
outputDir: 'static/assets/mermaid',
outputFormat: 'png',
concurrency: 4,
mmdcArgs: ['-b', 'transparent', '--scale', '1.5'],
},
],
// ...
],
presets: [
[
'classic',
{
docs: {
beforeDefaultRemarkPlugins: [remarkMermaidStatic],
// ...
},
},
],
],
// ...
};
Метаданные Mermaid
Вы можете добавить блок метаданных (похожий на frontmatter) в верхнюю часть любого блока mermaid. Это дает вам детальный контроль над доступностью и стилизацией.
Доступные поля метаданных
Вот доступные опции метаданных, которые вы можете использовать:
| Опция | Тип / По умолчанию | Описание |
|---|---|---|
id | String | Устанавливает HTML id для тега <figure>. Если не указан, используется 10-значный хэш кода диаграммы. Этот ID также определяет имя выходных файлов изображений. |
alt | String | Настоятельно рекомендуется. Устанавливает alt текст для тегов <img>. Критически важно для доступности — осмысленно опишите диаграмму (до 160 символов). |
caption | String | Добавляет элемент <figcaption> под диаграммой. |
width | String | Устанавливает атрибут width на тегах <img> (например, 600px). Полезно, когда отображаемые изображения слишком велики на настольных компьютерах. |
prerender | false | Если установлено значение false, этот плагин пропустит эту диаграмму полностью, оставив ее для рендеринга на стороне клиента с помощью @docusaurus/theme-mermaid. |
descriptionId | String | Расширенная функция доступности, связывающая figure с внешним описанием через aria-describedby. Используйте id существующего элемента HTML, который содержит текст описания (для WCAG-совместимости). |
Лицензия
Этот плагин выпущен под лицензией MIT. Вы можете свободно использовать, изменять и распространять его по своему усмотрению.
Участие в проекте
Вклад приветствуется! Если вы нашли ошибку или у вас есть запрос на новую функцию, пожалуйста, откройте issue в репозитории GitHub.