Skip to content

Commit

Permalink
Support Mermaid.js syntax via fenced code blocks.
Browse files Browse the repository at this point in the history
Closes kiwitcms/Kiwi#3116

if you type

```mermaid
<diagram code goes here>
```

this will be rendered as a PNG image via the https://mermaid.ink service
and the image will be automatically injected into the resulting HTML
once markdown is rendered.
  • Loading branch information
atodorov committed Jun 12, 2024
1 parent 61aa414 commit f505f86
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 1 deletion.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ system, dubbed *Enterprise Edition*, which contains the following changes:
* Versioned static files
* NGINX replaced by [OpenResty](https://openresty.org) with embedded
[Lua](https://github.com/openresty/lua-nginx-module) support
* Render Mermaid.js diagrams in Markdown fenced code blocks as PNG. Example
```
See an example flowchart below:
```mermaid
flowchart LR
Start --> Stop
```
```
* Add-ons:
- [django-ses](https://github.com/django-ses/django-ses) - Amazon SES email backend
- [dj-database-url](https://github.com/jacobian/dj-database-url) - DB configuration
Expand Down
52 changes: 52 additions & 0 deletions tcms_enterprise/markdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (c) 2024 Alexander Todorov <atodorov@otb.bg>
#
# Licensed under GNU Affero General Public License v3 or later (AGPLv3+)
# https://www.gnu.org/licenses/agpl-3.0.html

# pylint: disable=too-few-public-methods

import base64
import markdown


def mermaid2url(src_code):
"""
Convert a Mermaid source code into a viewable URL where the image
is generated by the Mermaid.Ink Web Service!
"""
as_base64 = base64.b64encode(src_code.encode("utf8"))
as_base64 = as_base64.decode("ascii")
return f"https://mermaid.ink/img/{as_base64}?type=png"


class MermaidPreprocessor(markdown.preprocessors.Preprocessor):
def run(self, lines):
new_lines = []
diagram_src = []
diagram_started = False

for line in lines:
if line.lower().find("```mermaid") > -1:
diagram_started = True
diagram_src = []
elif diagram_started and line.lower().strip() == "```":
diagram_started = False

image_url = mermaid2url("\n".join(diagram_src))
new_lines.append(f"![diagram.png]({image_url})")
elif diagram_started:
diagram_src.append(line)
else:
new_lines.append(line)

return new_lines


class KiwiTCMSExtension(markdown.extensions.Extension):
def extendMarkdown(self, md):
# Insert a preprocessor before ReferencePreprocessor
md.preprocessors.register(MermaidPreprocessor(md), 'mermaid', 35)


def makeExtension(**kwargs): # pylint: disable=invalid-name
return KiwiTCMSExtension(**kwargs)
7 changes: 6 additions & 1 deletion testing/configure_tenant_users.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2021 Alexander Todorov <atodorov@otb.bg>
# Copyright (c) 2021-2024 Alexander Todorov <atodorov@otb.bg>
#
# Licensed under GNU Affero General Public License v3 or later (AGPLv3+)
# https://www.gnu.org/licenses/agpl-3.0.html
Expand Down Expand Up @@ -36,4 +36,9 @@
product_version=version,
type=PlanType.objects.first(),
author=get_user_model().objects.last(),
text="""Kiwi TCMS Enterprise can render Mermaid.js diagrams, see:
```mermaid
flowchart LR
Start --> Stop
```"""
)
6 changes: 6 additions & 0 deletions testing/test_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ rlJournalStart
rlAssertGreaterOrEqual ">= 40 r/s" "$COMPLETED_REQUESTS" 400
rlPhaseEnd

rlPhaseStartTest "Should render Mermaid.JS diagrams"
rlRun -t -c "curl -L -k -b ./login-cookies.txt -o plan.html $HTTPS/plan/1/ 2>/dev/null"
rlAssertGrep "https://mermaid.ink/img/" plan.html
rlAssertNotGrep "flowchart LR" plan.html
rlPhaseEnd

rlPhaseStartCleanup
rlRun -t -c "docker kill keycloak_server"
rlRun -t -c "docker compose -f docker-compose.testing logs --no-color > docker.log"
Expand Down

0 comments on commit f505f86

Please sign in to comment.