@docusaurus/theme-mermaid 3.8.1 → 3.9.0-canary-6406

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,7 @@
7
7
  import { useState, useEffect, useMemo } from 'react';
8
8
  import { useColorMode, useThemeConfig } from '@docusaurus/theme-common';
9
9
  import mermaid from 'mermaid';
10
+ import { ensureLayoutsRegistered } from './layouts';
10
11
  // Stable className to allow users to easily target with CSS
11
12
  export const MermaidContainerClassName = 'docusaurus-mermaid-container';
12
13
  export function useMermaidThemeConfig() {
@@ -24,12 +25,13 @@ function useMermaidId() {
24
25
  Random client-only id, we don't care much but mermaid want an id so...
25
26
  Note: Mermaid doesn't like values provided by Rect.useId() and throws
26
27
  */
27
- // TODO 2025-2026: check if useId() now works
28
+ // TODO Docusaurus v4: check if useId() now works
28
29
  // It could work thanks to https://github.com/facebook/react/pull/32001
29
30
  // return useId(); // tried that, doesn't work ('#d:re:' is not a valid selector.)
30
31
  return useState(`mermaid-svg-${Math.round(Math.random() * 10000000)}`)[0];
31
32
  }
32
33
  async function renderMermaid({ id, text, config, }) {
34
+ await ensureLayoutsRegistered();
33
35
  /*
34
36
  Mermaid API is really weird :s
35
37
  It is a big mutable singleton with multiple config levels
@@ -48,7 +50,7 @@ async function renderMermaid({ id, text, config, }) {
48
50
  To use a new mermaid config (on colorMode change for example) we should
49
51
  update siteConfig, and it can only be done with initialize()
50
52
  */
51
- mermaid.mermaidAPI.initialize(config);
53
+ mermaid.initialize(config);
52
54
  try {
53
55
  return await mermaid.render(id, text);
54
56
  }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ declare global {
8
+ const __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: boolean;
9
+ }
10
+ export declare function ensureLayoutsRegistered(): Promise<void>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import mermaid from 'mermaid';
8
+ async function registerOptionalElkLayout() {
9
+ // Mermaid does not support ELK layouts by default
10
+ // See https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid-layout-elk
11
+ // ELK layouts are heavy, so we made it an optional peer dependency
12
+ // See https://github.com/facebook/docusaurus/pull/11357
13
+ if (__DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__) {
14
+ const elkLayout = (await import('@mermaid-js/layout-elk')).default;
15
+ mermaid.registerLayoutLoaders(elkLayout);
16
+ }
17
+ }
18
+ // Ensure we only try to register layouts once
19
+ let layoutsRegistered = false;
20
+ export async function ensureLayoutsRegistered() {
21
+ if (!layoutsRegistered) {
22
+ await registerOptionalElkLayout();
23
+ layoutsRegistered = true;
24
+ }
25
+ }
package/lib/index.d.ts CHANGED
@@ -5,5 +5,5 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { Plugin } from '@docusaurus/types';
8
- export default function themeMermaid(): Plugin<void>;
8
+ export default function themeMermaid(): Promise<Plugin<void>>;
9
9
  export { validateThemeConfig } from './validateThemeConfig';
package/lib/index.js CHANGED
@@ -8,7 +8,25 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.validateThemeConfig = void 0;
10
10
  exports.default = themeMermaid;
11
- function themeMermaid() {
11
+ /**
12
+ * Check if the optional @mermaid-js/layout-elk package is available.
13
+ * It's an optional peer dependency because it's heavy and most Mermaid users
14
+ * might not need it.
15
+ */
16
+ async function isElkLayoutPackageAvailable() {
17
+ try {
18
+ await import('@mermaid-js/layout-elk');
19
+ return true;
20
+ }
21
+ catch (e) {
22
+ return false;
23
+ }
24
+ }
25
+ async function themeMermaid() {
26
+ // For now, we infer based on package availability
27
+ // In the future, we could make it configurable so that users can disable it
28
+ // even if the package is installed?
29
+ const elkLayoutEnabled = await isElkLayoutPackageAvailable();
12
30
  return {
13
31
  name: 'docusaurus-theme-mermaid',
14
32
  getThemePath() {
@@ -17,6 +35,19 @@ function themeMermaid() {
17
35
  getTypeScriptThemePath() {
18
36
  return '../src/theme';
19
37
  },
38
+ configureWebpack(config, isServer, utils) {
39
+ return {
40
+ plugins: [
41
+ new utils.currentBundler.instance.DefinePlugin({
42
+ __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: JSON.stringify(
43
+ // We only need to include the layout registration code on the
44
+ // client side. This also solves a weird Webpack-only bug when
45
+ // compiling the server config due to the module being ESM-only.
46
+ !isServer && elkLayoutEnabled),
47
+ }),
48
+ ],
49
+ };
50
+ },
20
51
  };
21
52
  }
22
53
  var validateThemeConfig_1 = require("./validateThemeConfig");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-mermaid",
3
- "version": "3.8.1",
3
+ "version": "3.9.0-canary-6406",
4
4
  "description": "Mermaid components for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/theme-mermaid.d.ts",
@@ -33,11 +33,11 @@
33
33
  "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
34
34
  },
35
35
  "dependencies": {
36
- "@docusaurus/core": "3.8.1",
37
- "@docusaurus/module-type-aliases": "3.8.1",
38
- "@docusaurus/theme-common": "3.8.1",
39
- "@docusaurus/types": "3.8.1",
40
- "@docusaurus/utils-validation": "3.8.1",
36
+ "@docusaurus/core": "3.9.0-canary-6406",
37
+ "@docusaurus/module-type-aliases": "3.9.0-canary-6406",
38
+ "@docusaurus/theme-common": "3.9.0-canary-6406",
39
+ "@docusaurus/types": "3.9.0-canary-6406",
40
+ "@docusaurus/utils-validation": "3.9.0-canary-6406",
41
41
  "mermaid": ">=11.6.0",
42
42
  "tslib": "^2.6.0"
43
43
  },
@@ -45,11 +45,17 @@
45
45
  "react-test-renderer": "^18.0.0"
46
46
  },
47
47
  "peerDependencies": {
48
+ "@mermaid-js/layout-elk": "^0.1.9",
48
49
  "react": "^18.0.0 || ^19.0.0",
49
50
  "react-dom": "^18.0.0 || ^19.0.0"
50
51
  },
52
+ "peerDependenciesMeta": {
53
+ "@mermaid-js/layout-elk": {
54
+ "optional": true
55
+ }
56
+ },
51
57
  "engines": {
52
- "node": ">=18.0"
58
+ "node": ">=20.0"
53
59
  },
54
- "gitHead": "fa8ae13e668fcbc0481ce10c0a734e2a5b397293"
60
+ "gitHead": "796441f4f831278ffc57971fabcd4c730da9e9d7"
55
61
  }
@@ -8,6 +8,8 @@
8
8
  import {useState, useEffect, useMemo} from 'react';
9
9
  import {useColorMode, useThemeConfig} from '@docusaurus/theme-common';
10
10
  import mermaid from 'mermaid';
11
+ import {ensureLayoutsRegistered} from './layouts';
12
+
11
13
  import type {RenderResult, MermaidConfig} from 'mermaid';
12
14
  import type {ThemeConfig} from '@docusaurus/theme-mermaid';
13
15
 
@@ -37,7 +39,7 @@ function useMermaidId(): string {
37
39
  Note: Mermaid doesn't like values provided by Rect.useId() and throws
38
40
  */
39
41
 
40
- // TODO 2025-2026: check if useId() now works
42
+ // TODO Docusaurus v4: check if useId() now works
41
43
  // It could work thanks to https://github.com/facebook/react/pull/32001
42
44
  // return useId(); // tried that, doesn't work ('#d:re:' is not a valid selector.)
43
45
 
@@ -53,6 +55,8 @@ async function renderMermaid({
53
55
  text: string;
54
56
  config: MermaidConfig;
55
57
  }): Promise<RenderResult> {
58
+ await ensureLayoutsRegistered();
59
+
56
60
  /*
57
61
  Mermaid API is really weird :s
58
62
  It is a big mutable singleton with multiple config levels
@@ -71,7 +75,7 @@ async function renderMermaid({
71
75
  To use a new mermaid config (on colorMode change for example) we should
72
76
  update siteConfig, and it can only be done with initialize()
73
77
  */
74
- mermaid.mermaidAPI.initialize(config);
78
+ mermaid.initialize(config);
75
79
 
76
80
  try {
77
81
  return await mermaid.render(id, text);
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import mermaid from 'mermaid';
9
+
10
+ declare global {
11
+ // Global variable provided by bundler DefinePlugin
12
+ /* eslint-disable-next-line no-underscore-dangle */
13
+ const __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: boolean;
14
+ }
15
+
16
+ async function registerOptionalElkLayout() {
17
+ // Mermaid does not support ELK layouts by default
18
+ // See https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid-layout-elk
19
+ // ELK layouts are heavy, so we made it an optional peer dependency
20
+ // See https://github.com/facebook/docusaurus/pull/11357
21
+ if (__DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__) {
22
+ const elkLayout = (await import('@mermaid-js/layout-elk')).default;
23
+ mermaid.registerLayoutLoaders(elkLayout);
24
+ }
25
+ }
26
+
27
+ // Ensure we only try to register layouts once
28
+ let layoutsRegistered = false;
29
+ export async function ensureLayoutsRegistered(): Promise<void> {
30
+ if (!layoutsRegistered) {
31
+ await registerOptionalElkLayout();
32
+ layoutsRegistered = true;
33
+ }
34
+ }
package/src/index.ts CHANGED
@@ -7,7 +7,26 @@
7
7
 
8
8
  import type {Plugin} from '@docusaurus/types';
9
9
 
10
- export default function themeMermaid(): Plugin<void> {
10
+ /**
11
+ * Check if the optional @mermaid-js/layout-elk package is available.
12
+ * It's an optional peer dependency because it's heavy and most Mermaid users
13
+ * might not need it.
14
+ */
15
+ async function isElkLayoutPackageAvailable() {
16
+ try {
17
+ await import('@mermaid-js/layout-elk');
18
+ return true;
19
+ } catch (e) {
20
+ return false;
21
+ }
22
+ }
23
+
24
+ export default async function themeMermaid(): Promise<Plugin<void>> {
25
+ // For now, we infer based on package availability
26
+ // In the future, we could make it configurable so that users can disable it
27
+ // even if the package is installed?
28
+ const elkLayoutEnabled = await isElkLayoutPackageAvailable();
29
+
11
30
  return {
12
31
  name: 'docusaurus-theme-mermaid',
13
32
 
@@ -17,6 +36,21 @@ export default function themeMermaid(): Plugin<void> {
17
36
  getTypeScriptThemePath() {
18
37
  return '../src/theme';
19
38
  },
39
+
40
+ configureWebpack(config, isServer, utils) {
41
+ return {
42
+ plugins: [
43
+ new utils.currentBundler.instance.DefinePlugin({
44
+ __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: JSON.stringify(
45
+ // We only need to include the layout registration code on the
46
+ // client side. This also solves a weird Webpack-only bug when
47
+ // compiling the server config due to the module being ESM-only.
48
+ !isServer && elkLayoutEnabled,
49
+ ),
50
+ }),
51
+ ],
52
+ };
53
+ },
20
54
  };
21
55
  }
22
56