diff --git a/app/editor/menus/code.tsx b/app/editor/menus/code.tsx
index efcfbc8702..fd1979b66b 100644
--- a/app/editor/menus/code.tsx
+++ b/app/editor/menus/code.tsx
@@ -48,6 +48,9 @@ export default function codeMenuItems(
]
: remainingLangMenuItems;
+ const isEditingMermaid = !!(mermaidPluginKey.getState(state) as MermaidState)
+ ?.editingId;
+
return [
{
name: "copyToClipboard",
@@ -64,10 +67,7 @@ export default function codeMenuItems(
name: "edit_mermaid",
icon: ,
tooltip: dictionary.editDiagram,
- visible:
- !(mermaidPluginKey.getState(state) as MermaidState)?.editingId &&
- isMermaid(node) &&
- !readOnly,
+ visible: isMermaid(node) && !isEditingMermaid && !readOnly,
},
{
name: "separator",
@@ -77,7 +77,7 @@ export default function codeMenuItems(
icon: ,
tooltip: dictionary.wrapText,
active: () => node.attrs.wrap,
- visible: !readOnly,
+ visible: !readOnly && (!isMermaid(node) || isEditingMermaid),
},
{
name: "separator",
diff --git a/package.json b/package.json
index 39769cb83b..6b7508df34 100644
--- a/package.json
+++ b/package.json
@@ -78,6 +78,7 @@
"@hocuspocus/server": "1.1.2",
"@juggle/resize-observer": "^3.4.0",
"@linear/sdk": "^58.1.0",
+ "@mermaid-js/layout-elk": "^0.2.0",
"@modelcontextprotocol/sdk": "^1.25.1",
"@node-oauth/oauth2-server": "^5.2.0",
"@notionhq/client": "^2.3.0",
diff --git a/server/models/helpers/ProsemirrorHelper.tsx b/server/models/helpers/ProsemirrorHelper.tsx
index b2a08b2e72..37e8576fbb 100644
--- a/server/models/helpers/ProsemirrorHelper.tsx
+++ b/server/models/helpers/ProsemirrorHelper.tsx
@@ -583,6 +583,8 @@ export class ProsemirrorHelper {
if (mermaidElements.length) {
element.innerHTML = `
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
+ import elkLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs';
+ mermaid.registerLayoutLoaders(elkLayouts);
mermaid.initialize({
startOnLoad: true,
fontFamily: "inherit",
diff --git a/shared/editor/extensions/Mermaid.ts b/shared/editor/extensions/Mermaid.ts
index e3e9c53018..52c6a6640a 100644
--- a/shared/editor/extensions/Mermaid.ts
+++ b/shared/editor/extensions/Mermaid.ts
@@ -84,7 +84,25 @@ class MermaidRenderer {
document.body.appendChild(renderElement);
try {
- mermaid ??= (await import("mermaid")).default;
+ if (!mermaid) {
+ mermaid = (await import("mermaid")).default;
+ mermaid.registerLayoutLoaders([
+ {
+ name: "elk",
+ loader: async () => {
+ const { default: elkLayouts } =
+ await import("@mermaid-js/layout-elk");
+ const elkDef = elkLayouts.find(
+ (d: { name: string }) => d.name === "elk"
+ );
+ if (!elkDef) {
+ throw new Error("ELK layout not found");
+ }
+ return elkDef.loader();
+ },
+ },
+ ]);
+ }
mermaid.initialize({
startOnLoad: true,
suppressErrorRendering: true,
diff --git a/vite.config.ts b/vite.config.ts
index 93697d5569..c74789054b 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -190,6 +190,11 @@ export default () =>
test: /node_modules[\\/]styled-components/,
priority: 20,
},
+ {
+ name: "vendor-mermaid-elk",
+ test: /node_modules[\\/](@mermaid-js[\\/]layout-elk|elkjs)/,
+ priority: 25,
+ },
{
name: "vendor-mermaid",
test: /node_modules[\\/](mermaid|cytoscape|cytoscape-fcose|layout-base|dagre-d3-es|langium|chevrotain|roughjs|@mermaid-js)/,
diff --git a/yarn.lock b/yarn.lock
index 9bd7c72697..3300d8e40a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4394,6 +4394,18 @@ __metadata:
languageName: node
linkType: hard
+"@mermaid-js/layout-elk@npm:^0.2.0":
+ version: 0.2.0
+ resolution: "@mermaid-js/layout-elk@npm:0.2.0"
+ dependencies:
+ d3: "npm:^7.9.0"
+ elkjs: "npm:^0.9.3"
+ peerDependencies:
+ mermaid: ^11.0.2
+ checksum: 10c0/d4938770adc669dd7e271aa0688838c9c1ff47c75479ab0385dc51c7a4e5e5fc1df3ea9913c1493709b4640fd50064db181a42c1b36d005f20cb8e2537570b29
+ languageName: node
+ linkType: hard
+
"@mermaid-js/parser@npm:^0.6.3":
version: 0.6.3
resolution: "@mermaid-js/parser@npm:0.6.3"
@@ -12009,6 +12021,13 @@ __metadata:
languageName: node
linkType: hard
+"elkjs@npm:^0.9.3":
+ version: 0.9.3
+ resolution: "elkjs@npm:0.9.3"
+ checksum: 10c0/caf544ff4fce8442d1d3dd6dface176c9b2fe26fc1e34f56122828e6eef7d2d7fe70d3202f9f3ecf0feb6287d4c8430949f483e63e450a7454bb39ccffab3808
+ languageName: node
+ linkType: hard
+
"email-providers@npm:^1.14.0":
version: 1.14.0
resolution: "email-providers@npm:1.14.0"
@@ -17556,6 +17575,7 @@ __metadata:
"@hocuspocus/server": "npm:1.1.2"
"@juggle/resize-observer": "npm:^3.4.0"
"@linear/sdk": "npm:^58.1.0"
+ "@mermaid-js/layout-elk": "npm:^0.2.0"
"@modelcontextprotocol/sdk": "npm:^1.25.1"
"@node-oauth/oauth2-server": "npm:^5.2.0"
"@notionhq/client": "npm:^2.3.0"