Как управлять компоновкой диаграмм в Mermaid
Управляйте компоновкой диаграмм Mermaid 12 с помощью ELK или dagre. Настраивайте параметры глобально и для отдельных диаграмм, регулируйте ELK и возвращайте прежний вид.
В Mermaid 12 движок компоновки определяется ключом конфигурации layout. Для большинства графовых диаграмм по умолчанию используется ELK. Чтобы вернуть прежний движок, задайте layout: dagre во front matter или в mermaid.initialize().
Вы обновили Mermaid, пересобрали сайт документации, и блок-схема, которую никто не трогал, теперь выглядит иначе: у неё другая форма и другие цвета. Секция для типа диаграммы вида flowchart: { defaultRenderer: ... } из старого ответа это не исправит.
В статье разберём, что изменилось, где задаётся компоновка, какая настройка имеет приоритет, как настраивать ELK и почему откат может ни на что не повлиять. Основы блок-схем описаны в статье о создании блок-схем для рабочих процессов.
Ключевые выводы
- Начиная с Mermaid 12.0.0, блок-схемы, диаграммы состояний, классов, «сущность — связь», требований, вариантов использования и agentflow без явно заданной компоновки раскладываются движком ELK, а не dagre.
layout: dagreвозвращает прежнее расположение элементов, но не прежний внешний вид. Для полного рендеринга как до версии 12 нужныlayout: dagre,theme: defaultиlook: classic.- Front matter или директива в диаграмме переопределяют
mermaid.initialize(). Поэтому глобальная настройка dagre для всего сайта не действует на диаграмму, в которой компоновка задана явно. - В Mermaid 12 параметр
defaultRendererудалён из секций конфигурации flowchart, class и state. Вместо него используйте ключ верхнего уровняlayout. - Сборка tiny не содержит ELK и откатывается на dagre, если не подключить
@mermaid-js/layout-elk.
Что изменилось в Mermaid 12?
Начиная с Mermaid 12, диаграмма без явно указанной компоновки раскладывается движком ELK, а не dagre. Поэтому после обновления диаграмма, в которой ничего не менялось, может получить другую форму. На странице конфигурации Layouts перечислены семь типов диаграмм, для которых ELK теперь используется по умолчанию: flowchart, state, class, entity relationship, requirement, use case и agentflow. ELK поставляется в основном пакете и регистрируется автоматически. Для интеллект-карт (mindmap) по умолчанию по-прежнему используется cose-bilkent, а tidy-tree подключается из отдельного пакета @mermaid-js/layout-tidy-tree.
В примечаниях к выпуску mermaid@12.0.0 описано и второе изменение. Для более широкого набора типов диаграмм, перечисленного в разделе значений по умолчанию для отдельных диаграмм на странице тем оформления, темой по умолчанию стала redux-color, а стилем (look) по умолчанию — neo. Таким образом, диаграмма в v12 может выглядеть иначе по двум независимым причинам: сменился движок компоновки, а также сменились тема и стиль.
Где задаётся компоновка: front matter, initialize() или конфигурация типа?
Компоновку в Mermaid можно задать для одной диаграммы или для всех диаграмм на сайте. Кроме того, тему и стиль можно ограничить одним типом диаграмм. При конфликте настроек побеждает наиболее конкретная.
| Область действия | Где | Синтаксис | Приоритетнее, чем |
|---|---|---|---|
| Одна диаграмма | Front matter или директива | config: layout: dagre | Все уровни ниже |
| Все диаграммы | Верхний уровень mermaid.initialize() | { layout: 'dagre' } | Значения по умолчанию для типа и глобальные |
| Один тип диаграмм | Встроенное значение по умолчанию для типа | (задаётся Mermaid) | Глобальное значение по умолчанию |
| Всё | Глобальное значение по умолчанию | (задаётся Mermaid) | Ничего |
Согласно примечаниям к выпуску 12.0.0, порядок разрешения такой: сначала front matter или директива, затем initialize(), затем значение по умолчанию для типа диаграммы и, наконец, глобальное значение по умолчанию.
Вот как полностью откатить одну диаграмму:
---
config:
layout: dagre
theme: default
look: classic
---
flowchart LR
Request --> Auth{Valid token?}
Auth -->|yes| Handler
Auth -->|no| Reject
Для всего сайта: первый вызов ниже меняет только движок, поэтому новые цвета сохраняются. Второй вызов возвращает весь рендеринг в том виде, каким он был до версии 12:
mermaid.initialize({ layout: 'dagre' });
mermaid.initialize({ layout: 'dagre', theme: 'default', look: 'classic' });
В Mermaid 12 также можно ограничить действие theme, look и layout одним типом диаграмм, указав их в секции конфигурации этого типа. Значение для типа приоритетнее глобального значения, заданного там же. Чтобы переключить все диаграммы на dagre, но вернуть прежний внешний вид только диаграммам классов, оставьте layout на верхнем уровне, а theme и look поместите в секцию class, как показано на странице диаграмм классов:
mermaid.initialize({
layout: 'dagre',
class: { theme: 'default', look: 'classic' },
});
Front matter всегда приоритетнее mermaid.initialize(). Допустим, на сайте глобально задано layout: 'dagre', а в front matter одной из диаграмм объявлено layout: elk. Эта диаграмма будет отрисована с помощью ELK.
Когда компоновка ELK в Mermaid полезна и как её настроить?
Используйте ELK для больших или перегруженных диаграмм. Оставьте dagre, если небольшая диаграмма и так выглядит хорошо. Документация Mermaid позиционирует ELK как решение для больших и сложных графов, а dagre по-прежнему доступен как давно зарекомендовавшая себя послойная компоновка. Если до обновления диаграммы отображались хорошо, вернуться к dagre — вполне разумное решение.
В разделе о компоновке справочника по синтаксису описано несколько ключей для настройки ELK, в том числе следующие. mergeEdges объединяет параллельные рёбра. nodePlacementStrategy принимает значения SIMPLE, NETWORK_SIMPLEX, LINEAR_SEGMENTS или BRANDES_KOEPF; в пресете default по умолчанию используется BRANDES_KOEPF. nodePlacementAlignment задаёт выравнивание Брандеса — Кёпфа (например, BALANCED или NONE). Если параметр не указан, выравнивание берётся из пресета.
---
config:
layout: elk
elk:
mergeEdges: true
nodePlacementStrategy: NETWORK_SIMPLEX
---
flowchart TD
Build --> Test --> Deploy
Build --> Lint --> Deploy
Диаграммы, которые использовали ELK ещё до v12, тоже могут измениться, поскольку теперь по умолчанию применяется сбалансированное размещение по алгоритму Брандеса — Кёпфа. В схеме пресетов ELK перечислены четыре значения preset: legacy, default, modelOrder и depthFirst. Там указано, что depthFirst — прежнее значение по умолчанию, а legacy воспроизводит рендеринг ELK в том виде, каким он был до появления пресетов.
Вывод ELK менялся и в пределах версий 12.x:
- В Mermaid 12.1.0 появился параметр
orientFeedbackEdges, включённый по умолчанию. Ребро, идущее от узла, который получает данные из подграфа, обратно в этот подграф, теперь прокладывается вниз по потоку, а не в обход подграфа. - В Mermaid 12.2.0 ELK перестал выпрямлять конечный участок ребра, если из-за этого подпись оказалась бы поверх другого ребра.
config:
layout: elk
elk:
preset: legacy
orientFeedbackEdges: false
Какие варианты ELK и алгоритмы для отдельных подграфов доступны?
Помимо layout: elk, на странице Layouts документации Mermaid перечислены шесть вариантов ELK, которые можно указывать в качестве значения layout: elk.stress, elk.force, elk.mrtree, elk.sporeOverlap, elk.box и elk.rectpacking.
---
config:
layout: elk.mrtree
---
flowchart TD
Root --> API
Root --> Web
API --> Workers
Согласно примечаниям к выпуску 12.0.0, elk.box и elk.rectpacking размещают узлы, но не прокладывают рёбра, поэтому рёбра рисуются прямыми линиями от центра к центру.
Отдельный подграф может выбрать собственный алгоритм с помощью @{ algorithm: ... }. В тех же примечаниях к выпуску допустимыми значениями названы шесть перечисленных вариантов, а также elk.layered и elk.radial. Там же сказано о двух особенностях такого переопределения: неподдерживаемые значения Mermaid игнорирует с предупреждением, а если рёбра пересекают границу подграфа, вместо заданного используется унаследованный алгоритм.
Почему исправление компоновки не работает?
Большинство неудачных откатов объясняется одной из пяти причин. Проверяйте их в следующем порядке:
- Вы всё ещё задаёте
defaultRenderer. На странице синтаксиса блок-схем указано, что в v12 этот параметр удалён из секций flowchart, class и state. Используйте вместо негоlayout. - Вы задали только
layout: dagre. Тема redux-color и стиль neo по-прежнему активны. Задайте все три ключа. - Front matter переопределяет ваш
initialize(). Удалитеlayoutиз front matter этой диаграммы. - Имя компоновки написано с ошибкой или не зарегистрировано. Согласно примечаниям к выпуску, в этом случае Mermaid не выбрасывает ошибку, а откатывается на dagre с предупреждением. Проверьте консоль.
- Вы используете сборку tiny. См. следующий раздел.
Отказ от defaultRenderer — изменение в одну строку:
// Before (removed in v12)
mermaid.initialize({ flowchart: { defaultRenderer: 'elk' } });
// After
mermaid.initialize({ layout: 'elk' });
Если ваша платформа документации ещё не перешла на v12, эти ключи могут работать по-старому. Сверьтесь с документацией самой платформы.
Почему сборка tiny откатывается на dagre?
Сборка tiny не включает ELK, поэтому любая диаграмма, запрашивающая ELK, отрисовывается в ней с помощью dagre. Для этого случая по-прежнему публикуется пакет @mermaid-js/layout-elk. Выполните шаги по регистрации из раздела ELK and the tiny build документации по использованию. В обычной сборке существующие вызовы registerLayoutLoaders продолжают работать, но больше не нужны, и их можно удалить.
Заключение
Если диаграмма изменилась после обновления до Mermaid 12, причин почти всегда две: движок компоновки ELK и новые тема и стиль. Решите, что именно вы хотите вернуть. Если нужна только прежняя форма, задайте layout: dagre. Для полного рендеринга как до версии 12 задайте layout: dagre, theme: default и look: classic. Затем поищите в конфигурации оставшиеся настройки defaultRenderer и front matter, переопределяющий глобальные настройки сайта.
Часто задаваемые вопросы
Работает ли ключевое слово диаграммы flowchart-elk в Mermaid 12?
Да. В примечаниях к выпуску Mermaid 12.0.0 сказано, что flowchart-elk по-прежнему работает как явное ключевое слово диаграммы. Изменился именно параметр defaultRenderer. Mermaid не отклоняет его, а игнорирует, поэтому конфигурация, в которой он всё ещё задан, не вызывает ошибки, но и ни на что не влияет. Если диаграмма получала компоновку ELK благодаря значению 'elk' параметра defaultRenderer для flowchart, вместо него следует задать layout: elk.
Увеличивает ли встроенный ELK объём загрузки Mermaid 12?
Заметно увеличивается только однофайловая сборка. В ESM-сборках ELK выделен в отдельный чанк, который загружается, только когда он нужен диаграмме. Согласно примечаниям к выпуску 12.0.0, IIFE-сборка mermaid.min.js встраивает ELK и увеличивается примерно на 500 КБ в сжатом gzip виде. Сборка tiny не включает ELK, сохраняет прежний размер и обрабатывает запросы ELK с помощью dagre.
Можно ли задать параметры настройки ELK для всего сайта, а не во front matter каждой диаграммы?
Да. elk — это свойство верхнего уровня в схеме конфигурации Mermaid, поэтому его можно передать в mermaid.initialize() рядом с layout, например layout: 'elk' и объект elk с mergeEdges: true и nodePlacementStrategy: 'NETWORK_SIMPLEX'. Директива %%{init}%% принимает такой же объект elk для отдельной диаграммы. Front matter конкретной диаграммы по-прежнему переопределяет значения, заданные для всего сайта.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k