Skip to content

Commit

Permalink
feat: add support for viewing mermaid in the browser (#181)
Browse files Browse the repository at this point in the history
Implement `--view` flag for mermaid renderer

---------

Co-authored-by: haidaraM <[email protected]>
  • Loading branch information
haidaraM and haidaraM authored Mar 30, 2024
1 parent 6c40c59 commit 7b12565
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* feat: Add support for hiding empty plays and plays without roles https://github.com/haidaraM/ansible-playbook-grapher/pull/177.
* Add a new flag `--hide-empty-plays` to not show in the graph the plays that end up being empty after applying the filters.
* Add a new flag `--hide-plays-without-roles` to not show in the graph the plays that end up with no roles. Only roles at the play level and include_role as tasks are considered (no import_role).
* Add support for viewing mermaid graphs in the browse with `--view --renderer mermaid-flowchart` in https://github.com/haidaraM/ansible-playbook-grapher/pull/181
* refactor(internal): `PlaybookNode.plays` is now a method instead of property.
* refactor(internal): Do not access the `_compositions` in the child classes: use method from the CompositeNode.
* chore(deps): update black requirement from ~=24.1 to ~=24.2 by @dependabot in https://github.com/haidaraM/ansible-playbook-grapher/pull/175
Expand Down
39 changes: 34 additions & 5 deletions ansibleplaybookgrapher/renderer/mermaid.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from pathlib import Path
import json
import zlib
from base64 import urlsafe_b64encode
import webbrowser
from typing import Dict, Set, List

from ansible.utils.display import Display
Expand Down Expand Up @@ -113,14 +117,39 @@ def render(
)

if view:
# TODO: implement the view option
# https://github.com/mermaidjs/mermaid-live-editor/issues/41 and https://mermaid.ink/
display.warning(
"The --view option is not supported yet by the mermaid renderer"
)
MermaidFlowChartRenderer.view(mermaid_code)

return str(final_output_path_file)

@staticmethod
def view(mermaid_code: str):
"""
View the mermaid code in the browser using https://mermaid.live/
This is based on:
- https://github.com/mermaid-js/mermaid-live-editor/blob/b5978e6faf7635e39452855fb4d062d1452ab71b/src/lib/util/serde.ts#L19-L29
- https://github.com/mermaidjs/mermaid-live-editor/issues/41#issuecomment-1820242778
:param mermaid_code:
:return:
"""
graph_state = {
"code": mermaid_code,
"mermaid": {"theme": "default"},
"autoSync": True,
"updateDiagram": True,
}

compressed = zlib.compress(json.dumps(graph_state).encode("utf-8"), level=9)

url_path = f'pako:{urlsafe_b64encode(compressed).decode("utf-8")}'
url = f"https://mermaid.live/edit#{url_path}"

display.display(f"Mermaid live editor URL: {url}")

# Display url using the default browser in a new tag
webbrowser.open(url, new=2)


class MermaidFlowChartPlaybookBuilder(PlaybookBuilder):
def __init__(
Expand Down
12 changes: 11 additions & 1 deletion tests/test_mermaid_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def run_grapher(
# Explicitly add verbosity to the tests
additional_args.insert(0, "-vvv")

if os.environ.get("TEST_VIEW_GENERATED_FILE") == "1":
additional_args.insert(0, "--view")

playbook_paths = [os.path.join(FIXTURES_DIR, p_file) for p_file in playbook_files]
args = [__prog__]

Expand Down Expand Up @@ -59,11 +62,18 @@ def _common_tests(mermaid_path: str, playbook_paths: List[str], **kwargs):

# TODO: add proper tests on the mermaid code.
# Need a parser to make sure the outputs contain all the playbooks, plays, tasks and roles
# test if the file exist. It will exist only if we write in it.
# Test if the file exist. It will exist only if we write in it.
assert os.path.isfile(
mermaid_path
), f"The mermaid file should exist at '{mermaid_path}'"

with open(mermaid_path, "r") as mermaid_file:
mermaid_data = mermaid_file.read()
for playbook_path in playbook_paths:
assert (
playbook_path in mermaid_data
), "The playbook path should be in the generated code"


@pytest.mark.parametrize(
"playbook_file",
Expand Down

0 comments on commit 7b12565

Please sign in to comment.