Browse Source

Use the Mermaid API directly to fix nested diagram inside `ui.dialog` (#4692)

This PR fix #4518 magically by invoking the Mermaid API exactly as
prescribed here:

https://mermaid.js.org/config/usage.html#api-usage

I think the commit wraps it up very well: 

> Dear mermaid: we'll call API ourselves thankyouverymuch

Their code: 
```js
  element = document.querySelector('#graphDiv');
  const graphDefinition = 'graph TB\na-->b';
  const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition);
  element.innerHTML = svg;
  // This can also be written as `bindFunctions?.(element);` using the `?` shorthand.
  if (bindFunctions) {
    bindFunctions(element);
  }
```

My code:
```js
let element = queue.shift(); // same mindset
let innertext = this.content; // mine's from Vue
const { svg, bindFunctions } = await mermaid.render('graphDiv', innertext); // literally the same except variable names
element.innerHTML = svg; // literally the same
if (bindFunctions) {
   bindFunctions(element); // literally the same
}
```

If I had to guess, the reason it was fixed, is because '#graphDiv' does
not exist, and so Mermaid just "assumes full size" and renders the
proper diagram without being pinched to absolutely tiny.

Note that there are a couple of shortcomings which I haven't tested /
haven't fixed, so don't merge just yet.

- [x] what happens when we change the content? Does the mermaid diagram
update appropriately?
- [x] As of how, if there is syntax error, we lose the good-ol "Mermaid
Bomb" error screen. Should we have better means?
- [x] Are the Mermaid config respected (`{'securityLevel': 'loose',
...}` - allow running JavaScript when a node is clicked; `{'logLevel':
'info', ...}` - log debug info to the console) respected under this
approach?
- [x] Does this PR impact existing code? If so, how much? 
- [x] Passing 'graphDiv' when '#graphDiv' doesn't exist seems kinda
sketchy. Are we absolutely sure that's the way to go?

---


![image](https://github.com/user-attachments/assets/f9eb99ef-5072-4af8-bc32-5b6ea1f09497)

Perfect diagram, despite disable cache is false / disable cache is on
and no network throttle.

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
Evan Chan 1 week ago
parent
commit
cd1906a2c4
1 changed files with 11 additions and 16 deletions
  1. 11 16
      nicegui/elements/mermaid.js

+ 11 - 16
nicegui/elements/mermaid.js

@@ -1,8 +1,5 @@
 import mermaid from "mermaid";
 
-let is_running = false;
-const queue = [];
-
 export default {
   template: `<div></div>`,
   data: () => ({
@@ -24,20 +21,18 @@ export default {
     async update(content) {
       if (this.last_content === content) return;
       this.last_content = content;
-      this.$el.innerHTML = content;
-      this.$el.removeAttribute("data-processed");
-      queue.push(this.$el);
-      if (is_running) return;
-      is_running = true;
-      while (queue.length) {
-        try {
-          await mermaid.run({ nodes: [queue.shift()] });
-        } catch (error) {
-          console.error(error);
-          this.$emit("error", error);
-        }
+      try {
+        const { svg, bindFunctions } = await mermaid.render(this.$el.id + "_mermaid", content);
+        this.$el.innerHTML = svg;
+        bindFunctions?.(this.$el);
+      } catch (error) {
+        const { svg, bindFunctions } = await mermaid.render(this.$el.id + "_mermaid", "error");
+        this.$el.innerHTML = svg;
+        bindFunctions?.(this.$el);
+        const mermaidErrorFormat = { str: error.message, message: error.message, hash: error.name, error };
+        console.error(mermaidErrorFormat);
+        this.$emit("error", mermaidErrorFormat);
       }
-      is_running = false;
     },
   },
   props: {