Feature #44425
openRender Mermaid code blocks as diagrams
Description
This patch adds support for rendering code blocks written in Mermaid syntax as diagrams using Mermaid.js.
For example, with CommonMark:
```mermaid
flowchart LR
A[Start] --> B[Process]
B --> C[End]
```
Or with Textile:
<pre><code class="mermaid">
flowchart LR
A[Start] --> B[Process]
B --> C[End]
</code></pre>
These are rendered as diagrams instead of code blocks:

This allows flowcharts, sequence diagrams, class diagrams, and other diagrams to be described as text in wikis, issue descriptions, and other formatted text fields.
Mermaid.js is widely used, and supporting it in Redmine would make it possible to preserve information in a more visual form using diagrams.
Implementation¶
- Adds mermaid.min.js 11.17.2
- Detects
mermaidcode blocks and renders them as diagrams - Loads Mermaid.js lazily only when a Mermaid code block is present, since the library is several MB in size
- Handles invalid Mermaid syntax without affecting the rest of the page
- Uses
securityLevel: 'strict'to prevent scripts and other unsafe content from being executed from Mermaid diagrams - Supports both Textile and CommonMark
- Adds license information for Mermaid.js and its bundled dependencies
- Adds tests for the above behavior
Patch¶
The patch could not be attached directly to this issue because it exceeds the attachment size limit, so it is available from the following GitHub pull request instead: https://patch-diff.githubusercontent.com/raw/ishikawa999/redmine/pull/19.patch
(Source: https://github.com/ishikawa999/redmine/pull/19 )
To download and apply the patch:
curl -o mermaid.patch https://patch-diff.githubusercontent.com/raw/ishikawa999/redmine/pull/19.patch git am mermaid.patch
Files
Updated by Go MAEDA 21 days ago
Mermaid has become widely adopted for creating diagrams in Markdown-based tools, and is supported by major platforms such as GitHub, GitLab, Azure DevOps, and Obsidian. I think Mermaid support would be a valuable addition to Redmine.
As a side benefit, having Mermaid.js available in Redmine could also support future UI improvements beyond Mermaid markup in formatted text. For example, it could be used for workflow visualization (#559) or issue dependency graphs (#2448).
Updated by Florian Walchshofer 20 days ago
Thanks for the patch. Overall, I like the implementation. The amount of core changes is relatively small, Mermaid is loaded only when needed, and features such as lazy loading and one-time initialization are implemented cleanly.
I also agree with Go MAEDA that having Mermaid support available directly in Redmine could enable additional use cases beyond wiki content.
One concern is that Mermaid is a rather actively developed project with frequent releases. Bundling it in Redmine core means tracking Mermaid updates, security fixes and related third-party dependencies over time. An alternative approach could be an optional Mermaid CLI/CGI integration with server-side SVG/PNG generation, allowing each Redmine installation to decide whether to enable it and keeping Mermaid outside the core dependency chain.
However, this would also make the integration and deployment more complex. Therefore, I still support the proposed JavaScript integration, as it is simple, widely adopted and probably the most practical solution for most Redmine installations.
Regarding the current patch itself, I only have one question:
mermaid.run({ nodes: [container], suppressErrors: true })
From my testing, with suppressErrors: false Mermaid parser and validation errors are propagated to the Promise rejection handler, for example invalid diagram types or syntax errors. This causes the .catch() block to run, while the original code block remains visible.
With suppressErrors: true, these errors no longer seem to reach the .catch() block, so no error is logged and the Mermaid-generated error rendering is shown instead.
Would it make sense to use suppressErrors: false here, hide the Mermaid error output, and log or display the actual parser error object?
The error details often include the exact line and syntax problem, which can be very helpful for users debugging Mermaid diagrams.
Updated by Mizuki ISHIKAWA 20 days ago
Florian Walchshofer wrote in #note-3:
One concern is that Mermaid is a rather actively developed project with frequent releases. Bundling it in Redmine core means tracking Mermaid updates, security fixes and related third-party dependencies over time. An alternative approach could be an optional Mermaid CLI/CGI integration with server-side SVG/PNG generation, allowing each Redmine installation to decide whether to enable it and keeping Mermaid outside the core dependency chain.
Thank you for the feedback.
I have not tested this approach yet, but I think it should be possible to enable Mermaid conversion only when Mermaid CLI is available, similar to other features that depend on external commands such as Ghostscript or ImageMagick.
Personally, I prefer the Mermaid.js approach because the implementation is simpler. However, if the Mermaid CLI approach is considered preferable given the maintenance burden of keeping Mermaid.js and its dependencies up to date, I would respect that decision.
With suppressErrors: true, these errors no longer seem to reach the .catch() block, so no error is logged and the Mermaid-generated error rendering is shown instead.
You're right. I've updated the pull request. https://github.com/ishikawa999/redmine/pull/19/changes/71ca601f747d8cccb67816ddb9ec87f1ebebb5fb
Updated by Marius BĂLTEANU 20 days ago
Florian Walchshofer wrote in #note-3:
[..]
One concern is that Mermaid is a rather actively developed project with frequent releases. Bundling it in Redmine core means tracking Mermaid updates, security fixes and related third-party dependencies over time. An alternative approach could be an optional Mermaid CLI/CGI integration with server-side SVG/PNG generation, allowing each Redmine installation to decide whether to enable it and keeping Mermaid outside the core dependency chain.
That also means the integration can break after a server-side Mermaid CLI/CGI update. Additionally, server-side rendering requires Puppeteer, which makes installation and maintenance much more complex.
Overall, I am in favor of bundling the JS library inside Redmine. We can cut new releases for important upstream security fixes, just as we already do for other dependencies.
Updated by Florian Walchshofer 19 days ago
- File 0003-parse-error-to-flash-error-message.patch 0003-parse-error-to-flash-error-message.patch added
Thanks for the clarification.
I tried an alternative approach based on suppressErrors: false
With the attached patch, Mermaid rendering errors are handled in the Promise rejection handler. Instead of rendering Mermaid's built-in error diagram, a standard Redmine flash message is shown and the original source block remains visible for inspection and copying.
This also brings the behaviour closer to GitHub's Mermaid integration, which displays an error message while keeping the original diagram source visible.
The corresponding system tests were updated to cover both successful rendering and invalid Mermaid diagrams.
This patch is intended as an additional change on top of the current pull request.
Without a rejection handler, using suppressErrors: false results in unhandled Promise rejections whenever Mermaid parsing or rendering fails.
Updated by Mizuki ISHIKAWA 19 days ago
Florian Walchshofer wrote in #note-6:
I tried an alternative approach based on
suppressErrors: false
I applied the patch and tested it locally.
I think the error messages are much easier to read now.
Since the error messages are generated by Mermaid.js, they cannot be localized, but I think this is acceptable.
Updated by Helder Costa 18 days ago
It will be greate that PDF export also render mermaid blocks correctly!
Thanks
Updated by Go MAEDA 18 days ago
Helder Costa wrote in #note-8:
It will be greate that PDF export also render mermaid blocks correctly!
Thanks for the suggestion. I agree that rendering Mermaid diagrams in PDF exports would be a great addition. However, supporting PDF export would significantly increase the scope of this feature.
In my opinion, we should first focus on making Mermaid available on Redmine's web pages, and consider PDF export as a future improvement after the web support is complete.
Updated by Mizuki ISHIKAWA 12 days ago
I updated the implementation to support Mermaid.js 12.0.0 and incorporated 0003-parse-error-to-flash-error-message.patch by Florian Walchshofer, along with some other changes, and pushed the updates to https://github.com/ishikawa999/redmine/pull/19 .
Updated by Go MAEDA 12 days ago
I have tested the latest patch, and I have not found any issues that would block merging it.
Since there is still enough time before Redmine 7.1.0, I am planning to commit this to trunk in the next few days. This will allow more people to try Mermaid support in real-world use and give us time to address any issues that may be found before the release.
Please let me know if you have any concerns.
Updated by Marius BĂLTEANU 11 days ago
Go MAEDA wrote in #note-11:
I have tested the latest patch, and I have not found any issues that would block merging it.
Since there is still enough time before Redmine 7.1.0, I am planning to commit this to trunk in the next few days. This will allow more people to try Mermaid support in real-world use and give us time to address any issues that may be found before the release.
Please let me know if you have any concerns.
I'm in favour of adding this to the core as soon as possible.