mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-26 01:33:02 +00:00
feat(mermaid): support elk layout (#11357)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
This commit is contained in:
parent
c131034bc2
commit
305910758b
|
|
@ -46,7 +46,13 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
"react-dom": "^18.0.0 || ^19.0.0",
|
||||
"@mermaid-js/layout-elk": "^0.1.9"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@mermaid-js/layout-elk": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
import {useState, useEffect, useMemo} from 'react';
|
||||
import {useColorMode, useThemeConfig} from '@docusaurus/theme-common';
|
||||
import mermaid from 'mermaid';
|
||||
import {ensureLayoutsRegistered} from './layouts';
|
||||
|
||||
import type {RenderResult, MermaidConfig} from 'mermaid';
|
||||
import type {ThemeConfig} from '@docusaurus/theme-mermaid';
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ function useMermaidId(): string {
|
|||
Note: Mermaid doesn't like values provided by Rect.useId() and throws
|
||||
*/
|
||||
|
||||
// TODO 2025-2026: check if useId() now works
|
||||
// TODO Docusaurus v4: check if useId() now works
|
||||
// It could work thanks to https://github.com/facebook/react/pull/32001
|
||||
// return useId(); // tried that, doesn't work ('#d:re:' is not a valid selector.)
|
||||
|
||||
|
|
@ -53,6 +55,8 @@ async function renderMermaid({
|
|||
text: string;
|
||||
config: MermaidConfig;
|
||||
}): Promise<RenderResult> {
|
||||
await ensureLayoutsRegistered();
|
||||
|
||||
/*
|
||||
Mermaid API is really weird :s
|
||||
It is a big mutable singleton with multiple config levels
|
||||
|
|
@ -71,7 +75,7 @@ async function renderMermaid({
|
|||
To use a new mermaid config (on colorMode change for example) we should
|
||||
update siteConfig, and it can only be done with initialize()
|
||||
*/
|
||||
mermaid.mermaidAPI.initialize(config);
|
||||
mermaid.initialize(config);
|
||||
|
||||
try {
|
||||
return await mermaid.render(id, text);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import mermaid from 'mermaid';
|
||||
|
||||
declare global {
|
||||
// Global variable provided by bundler DefinePlugin
|
||||
/* eslint-disable-next-line no-underscore-dangle */
|
||||
const __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: boolean;
|
||||
}
|
||||
|
||||
async function registerOptionalElkLayout() {
|
||||
// Mermaid does not support ELK layouts by default
|
||||
// See https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid-layout-elk
|
||||
// ELK layouts are heavy, so we made it an optional peer dependency
|
||||
// See https://github.com/facebook/docusaurus/pull/11357
|
||||
if (__DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__) {
|
||||
const elkLayout = (await import('@mermaid-js/layout-elk')).default;
|
||||
mermaid.registerLayoutLoaders(elkLayout);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we only try to register layouts once
|
||||
let layoutsRegistered = false;
|
||||
export async function ensureLayoutsRegistered(): Promise<void> {
|
||||
if (!layoutsRegistered) {
|
||||
await registerOptionalElkLayout();
|
||||
layoutsRegistered = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,26 @@
|
|||
|
||||
import type {Plugin} from '@docusaurus/types';
|
||||
|
||||
export default function themeMermaid(): Plugin<void> {
|
||||
/**
|
||||
* Check if the optional @mermaid-js/layout-elk package is available.
|
||||
* It's an optional peer dependency because it's heavy and most Mermaid users
|
||||
* might not need it.
|
||||
*/
|
||||
async function isElkLayoutPackageAvailable() {
|
||||
try {
|
||||
await import('@mermaid-js/layout-elk');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function themeMermaid(): Promise<Plugin<void>> {
|
||||
// For now, we infer based on package availability
|
||||
// In the future, we could make it configurable so that users can disable it
|
||||
// even if the package is installed?
|
||||
const elkLayoutEnabled = await isElkLayoutPackageAvailable();
|
||||
|
||||
return {
|
||||
name: 'docusaurus-theme-mermaid',
|
||||
|
||||
|
|
@ -17,6 +36,21 @@ export default function themeMermaid(): Plugin<void> {
|
|||
getTypeScriptThemePath() {
|
||||
return '../src/theme';
|
||||
},
|
||||
|
||||
configureWebpack(config, isServer, utils) {
|
||||
return {
|
||||
plugins: [
|
||||
new utils.currentBundler.instance.DefinePlugin({
|
||||
__DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: JSON.stringify(
|
||||
// We only need to include the layout registration code on the
|
||||
// client side. This also solves a weird Webpack-only bug when
|
||||
// compiling the server config due to the module being ESM-only.
|
||||
!isServer && elkLayoutEnabled,
|
||||
),
|
||||
}),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ Csapo
|
|||
Csvg
|
||||
Dabit
|
||||
dabit
|
||||
dagre
|
||||
Daishi
|
||||
Datagit
|
||||
datagit
|
||||
|
|
|
|||
|
|
@ -447,3 +447,88 @@ architecture-beta
|
|||
disk1:T -- B:server
|
||||
disk2:T -- B:db
|
||||
```
|
||||
|
||||
## ELK Styling
|
||||
|
||||
Mermaid provides an [ELK layout](https://mermaid.js.org/syntax/entityRelationshipDiagram.html#layout)
|
||||
|
||||
### Dagre
|
||||
|
||||
This is a "classical" Mermaid diagram, using the default Dagre layout.
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
|
||||
COMPANY ||--o{ DEPARTMENT : has
|
||||
COMPANY ||--o{ PROJECT : undertakes
|
||||
COMPANY ||--o{ LOCATION : operates_in
|
||||
COMPANY ||--o{ CLIENT : serves
|
||||
|
||||
DEPARTMENT ||--o{ EMPLOYEE : employs
|
||||
DEPARTMENT ||--o{ PROJECT : manages
|
||||
DEPARTMENT ||--o{ BUDGET : allocated
|
||||
|
||||
EMPLOYEE }o--o{ PROJECT : works_on
|
||||
EMPLOYEE ||--|| ADDRESS : lives_at
|
||||
EMPLOYEE }o--o{ SKILL : has
|
||||
EMPLOYEE ||--o{ DEPENDENT : supports
|
||||
|
||||
PROJECT ||--o{ CLIENT : for
|
||||
PROJECT ||--o{ TASK : contains
|
||||
|
||||
```
|
||||
|
||||
### ELK er diagram layout
|
||||
|
||||
This ER diagram should look different, using the ELK layout.
|
||||
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
erDiagram
|
||||
|
||||
COMPANY ||--o{ DEPARTMENT : has
|
||||
COMPANY ||--o{ PROJECT : undertakes
|
||||
COMPANY ||--o{ LOCATION : operates_in
|
||||
COMPANY ||--o{ CLIENT : serves
|
||||
|
||||
DEPARTMENT ||--o{ EMPLOYEE : employs
|
||||
DEPARTMENT ||--o{ PROJECT : manages
|
||||
DEPARTMENT ||--o{ BUDGET : allocated
|
||||
|
||||
EMPLOYEE }o--o{ PROJECT : works_on
|
||||
EMPLOYEE ||--|| ADDRESS : lives_at
|
||||
EMPLOYEE }o--o{ SKILL : has
|
||||
EMPLOYEE ||--o{ DEPENDENT : supports
|
||||
|
||||
PROJECT ||--o{ CLIENT : for
|
||||
PROJECT ||--o{ TASK : contains
|
||||
|
||||
```
|
||||
|
||||
Mermaid also provides a way of setting config parameters using a directive `%%{init:{"layout":"elk"}}%%`
|
||||
|
||||
```mermaid
|
||||
%%{init:{"layout":"elk"}}%%
|
||||
erDiagram
|
||||
|
||||
COMPANY ||--o{ DEPARTMENT : has
|
||||
COMPANY ||--o{ PROJECT : undertakes
|
||||
COMPANY ||--o{ LOCATION : operates_in
|
||||
COMPANY ||--o{ CLIENT : serves
|
||||
|
||||
DEPARTMENT ||--o{ EMPLOYEE : employs
|
||||
DEPARTMENT ||--o{ PROJECT : manages
|
||||
DEPARTMENT ||--o{ BUDGET : allocated
|
||||
|
||||
EMPLOYEE }o--o{ PROJECT : works_on
|
||||
EMPLOYEE ||--|| ADDRESS : lives_at
|
||||
EMPLOYEE }o--o{ SKILL : has
|
||||
EMPLOYEE ||--o{ DEPENDENT : supports
|
||||
|
||||
PROJECT ||--o{ CLIENT : for
|
||||
PROJECT ||--o{ TASK : contains
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -99,3 +99,36 @@ import Mermaid from '@theme/Mermaid';
|
|||
C-->D;`}
|
||||
/>
|
||||
```
|
||||
|
||||
## Layouts
|
||||
|
||||
Mermaid supports different [layout engines](https://mermaid.js.org/intro/syntax-reference.html#layout-and-look):
|
||||
|
||||
- The `dagre` layout engine is supported by default in Docusaurus.
|
||||
- The `elk` layout engine is heavier and can be enabled by installing the optional `@mermaid-js/layout-elk` dependency.
|
||||
|
||||
````md
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
````
|
||||
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
"@docusaurus/theme-mermaid": "3.8.1",
|
||||
"@docusaurus/utils": "3.8.1",
|
||||
"@docusaurus/utils-common": "3.8.1",
|
||||
"@mermaid-js/layout-elk": "^0.1.9",
|
||||
"clsx": "^2.0.0",
|
||||
"color": "^4.2.3",
|
||||
"fs-extra": "^11.1.1",
|
||||
|
|
|
|||
13
yarn.lock
13
yarn.lock
|
|
@ -2591,6 +2591,14 @@
|
|||
dependencies:
|
||||
"@types/mdx" "^2.0.0"
|
||||
|
||||
"@mermaid-js/layout-elk@^0.1.9":
|
||||
version "0.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@mermaid-js/layout-elk/-/layout-elk-0.1.9.tgz#c773b9454875858a2f45412fe04502bccec83cf2"
|
||||
integrity sha512-HuvaqFZBr6yT9PpWYockvKAZPJVd89yn/UjOYPxhzbZxlybL2v+2BjVCg7MVH6vRs1irUohb/s42HEdec1CCZw==
|
||||
dependencies:
|
||||
d3 "^7.9.0"
|
||||
elkjs "^0.9.3"
|
||||
|
||||
"@mermaid-js/parser@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.4.0.tgz#c1de1f5669f8fcbd0d0c9d124927d36ddc00d8a6"
|
||||
|
|
@ -7937,6 +7945,11 @@ electron-to-chromium@^1.5.160:
|
|||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz#477b0957e42f071905a86f7c905a9848f95d2bdb"
|
||||
integrity sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==
|
||||
|
||||
elkjs@^0.9.3:
|
||||
version "0.9.3"
|
||||
resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.9.3.tgz#16711f8ceb09f1b12b99e971b138a8384a529161"
|
||||
integrity sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==
|
||||
|
||||
emittery@^0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
|
||||
|
|
|
|||
Loading…
Reference in New Issue