')
continue
- match_mermaid_codeblock_start = MERMAID_CODEBLOCK_START.match(line)
- if match_mermaid_codeblock_start:
- exist_mermaid_codeblock = True
- in_mermaid_codeblock = True
- codeblock_sign = match_mermaid_codeblock_start.group("code_block_sign")
- codeblock_end_pattern = re.compile(rf"{codeblock_sign}\s*")
- result_lines.append('
')
- continue
-
- result_lines.append(line)
-
- if exist_mermaid_codeblock:
- result_lines.extend(MERMAID_JS_SCRIPT.split("\n"))
- return result_lines
+ result_lines.append(line)
+ if exist_mermaid_codeblock:
+ result_lines.extend(self.generate_mermaid_init_script())
+ return result_lines
-class MermaidPreprocessor(Preprocessor):
def run(self, lines: list[str]) -> list[str]:
- return add_mermaid_script_and_tag(lines)
+ return self.add_mermaid_script_and_tag(lines)
class MermaidExtension(Extension):
- """Add source code highlighting to markdown codeblocks."""
+ """Add mermaid diagram markdown codeblocks."""
+
+ def __init__(self, **kwargs: dict[str, Any]) -> None:
+ self.config = {
+ "icon_packs": [
+ {},
+ "Dictionary of icon packs to use: { name(str) : url(str) }. Default: {} (no icon packs). example: { 'logos' : 'https://unpkg.com/@iconify-json/logos@1/icons.json' } corresponds to the json file example here: https://mermaid.js.org/config/icons.html",
+ ],
+ }
+
+ super().__init__(**kwargs)
+
+ self.icon_packs: dict[str, str] = {}
+ config_packs = (
+ self.getConfig("icon_packs", default={}) or {}
+ ) # for the None case
+ self.icon_packs.update(config_packs)
def extendMarkdown(self, md: Markdown) -> None:
- """Add HilitePostprocessor to Markdown instance."""
+ """Add MermaidExtension to Markdown instance."""
# Insert a preprocessor before ReferencePreprocessor
- md.preprocessors.register(MermaidPreprocessor(md), "mermaid", 35)
+
+ md.preprocessors.register(
+ MermaidPreprocessor(md, icon_packs=self.icon_packs), "mermaid", 35
+ )
md.registerExtension(self)
diff --git a/pyproject.toml b/pyproject.toml
index 591b021..e824a7c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,10 @@
[project]
name = "markdown-mermaidjs"
version = "1.0.0"
-authors = [{ name = "Wei Lee", email = "weilee.rx@gmail.com" }]
+authors = [
+ { name = "Wei Lee", email = "weilee.rx@gmail.com" },
+ { name = "Owyn Richen", email = "owynrichen@gmail.com" },
+]
description = "Python-Markdown extension to add Mermaid graph"
license = "GPL-3.0-only"
readme = "docs/README.md"
@@ -35,15 +38,14 @@ test = [
"pytest-cov>=6.0.0",
"pytest-mock>=3.14.0",
]
-style = [
- "mypy>=1.14.1",
- "ruff>=0.9.2",
- "types-markdown>=3.7.0.20241204",
-]
+style = ["mypy>=1.14.1", "ruff>=0.9.2", "types-markdown>=3.7.0.20241204"]
security = ["bandit>=1.2.2", "pip-audit>=2.7.3"]
git = ["commitizen>=4.1.0", "pre-commit>=4.0.1"]
doc = ["mkdocs>=1.6.1", "mkdocs-material>=9.5.50"]
+[tool.uv]
+default-groups = ["dev", "test", "style", "security", "git"]
+
[tool.commitizen]
name = "cz_conventional_commits"
diff --git a/tests/data/test_icons_1.md b/tests/data/test_icons_1.md
new file mode 100644
index 0000000..6e18064
--- /dev/null
+++ b/tests/data/test_icons_1.md
@@ -0,0 +1,36 @@
+# Title
+
+Testing 'registerIconPacks' as used by https://mermaid.js.org/syntax/architecture.html.
+
+```mermaid
+architecture-beta
+ group api(logos:aws-lambda)[API]
+
+ service db(logos:aws-aurora)[Database] in api
+ service disk1(logos:aws-glacier)[Storage] in api
+ service disk2(logos:aws-s3)[Storage] in api
+ service server(logos:aws-ec2)[Server] in api
+
+ db:L -- R:server
+ disk1:T -- B:server
+ disk2:T -- B:db
+```
+
+It only supports full url lazy-loading: https://mermaid.js.org/config/icons.html
+
+~~~mermaid
+architecture-beta
+ group api(logos:aws-lambda)[API]
+
+ service db(logos:aws-aurora)[Database] in api
+ service disk1(logos:aws-glacier)[Storage] in api
+ service disk2(logos:aws-s3)[Storage] in api
+ service server(logos:aws-ec2)[Server] in api
+
+ db:L -- R:server
+ disk1:T -- B:server
+ disk2:T -- B:db
+~~~
+
+
+End of the file
diff --git a/tests/data/test_icons_2.md b/tests/data/test_icons_2.md
new file mode 100644
index 0000000..8989e2e
--- /dev/null
+++ b/tests/data/test_icons_2.md
@@ -0,0 +1,5 @@
+# Title
+
+Some text.
+
+End of the file
diff --git a/tests/test_markdown_mermaid.py b/tests/test_markdown_mermaid.py
index 804ae63..7088dfa 100644
--- a/tests/test_markdown_mermaid.py
+++ b/tests/test_markdown_mermaid.py
@@ -2,9 +2,10 @@
from pathlib import Path
+import markdown
import pytest
-from markdown_mermaidjs.markdown_mermaidjs import add_mermaid_script_and_tag
+from markdown_mermaidjs.markdown_mermaidjs import MermaidExtension, MermaidPreprocessor
data_dir = Path("tests/data")
@@ -15,5 +16,85 @@
def test_add_mermaid_script_and_tag(data_regression, input_file_path):
with open(input_file_path) as input_file:
lines = input_file.readlines()
- result_lines = add_mermaid_script_and_tag(lines)
+
+ mermaid_preprocessor = MermaidPreprocessor(MermaidExtension())
+
+ result_lines = mermaid_preprocessor.add_mermaid_script_and_tag(lines)
+ data_regression.check("\n".join(result_lines))
+
+
+def test_configure_icon_packs():
+ mermaid_extension = MermaidExtension(
+ icon_packs={"logos": "https://unpkg.com/@iconify-json/logos@1/icons.json"}
+ )
+ assert mermaid_extension.icon_packs == {
+ "logos": "https://unpkg.com/@iconify-json/logos@1/icons.json"
+ }
+
+
+def test_configure_icon_packs_default():
+ mermaid_extension = MermaidExtension()
+ assert mermaid_extension.icon_packs == {}
+
+
+@pytest.mark.parametrize(
+ ("input_icon_packs", "expected_output"),
+ [
+ (
+ {"logos": "https://unpkg.com/@iconify-json/logos@1/icons.json"},
+ {"logos": "https://unpkg.com/@iconify-json/logos@1/icons.json"},
+ ),
+ (
+ {
+ "logos": "https://unpkg.com/@iconify-json/logos@1/icons.json",
+ "hugeicons": "https://unpkg.com/@iconify-json/hugeicons@1/icons.json",
+ },
+ {
+ "logos": "https://unpkg.com/@iconify-json/logos@1/icons.json",
+ "hugeicons": "https://unpkg.com/@iconify-json/hugeicons@1/icons.json",
+ },
+ ),
+ (None, {}),
+ ],
+)
+def test_extension_configuration_icon_packs(input_icon_packs, expected_output):
+ mermaid_extension = MermaidExtension(icon_packs=input_icon_packs)
+
+ markdown_instance = markdown.Markdown(extensions=[mermaid_extension])
+
+ mermaid_preprocessor = markdown_instance.preprocessors[0]
+ assert mermaid_preprocessor.icon_packs == expected_output
+
+ markdown_instance2 = markdown.Markdown(
+ extensions=["markdown_mermaidjs"],
+ extension_configs={"markdown_mermaidjs": {"icon_packs": input_icon_packs}},
+ )
+
+ mermaid_preprocessor2 = markdown_instance2.preprocessors[0]
+ assert mermaid_preprocessor2.icon_packs == expected_output
+
+
+@pytest.mark.parametrize(
+ "input_file_path", [data_dir / "test_icons_1.md", data_dir / "test_icons_2.md"]
+)
+def test_add_mermaid_script_and_tag_with_icons(data_regression, input_file_path):
+ with open(input_file_path) as input_file:
+ lines = input_file.readlines()
+
+ markdown_instance = markdown.Markdown(
+ extensions=["markdown_mermaidjs"],
+ extension_configs={
+ "markdown_mermaidjs": {
+ "icon_packs": {
+ "logos": "https://unpkg.com/@iconify-json/logos@1/icons.json"
+ }
+ }
+ },
+ )
+ mermaid_preprocessor = MermaidPreprocessor(
+ md=markdown_instance,
+ icon_packs={"logos": "https://unpkg.com/@iconify-json/logos@1/icons.json"},
+ )
+
+ result_lines = mermaid_preprocessor.add_mermaid_script_and_tag(lines)
data_regression.check("\n".join(result_lines))
diff --git a/tests/test_markdown_mermaid/test_add_mermaid_script_and_tag_with_icons_input_file_path0_.yml b/tests/test_markdown_mermaid/test_add_mermaid_script_and_tag_with_icons_input_file_path0_.yml
new file mode 100644
index 0000000..d4fda07
--- /dev/null
+++ b/tests/test_markdown_mermaid/test_add_mermaid_script_and_tag_with_icons_input_file_path0_.yml
@@ -0,0 +1,14 @@
+"# Title\n\n\n\nTesting 'registerIconPacks' as used by https://mermaid.js.org/syntax/architecture.html.\n\
+ \n\n\n
\narchitecture-beta\n\n group api(logos:aws-lambda)[API]\n\
+ \n\n\n service db(logos:aws-aurora)[Database] in api\n\n service disk1(logos:aws-glacier)[Storage]\
+ \ in api\n\n service disk2(logos:aws-s3)[Storage] in api\n\n service server(logos:aws-ec2)[Server]\
+ \ in api\n\n\n\n db:L -- R:server\n\n disk1:T -- B:server\n\n disk2:T --\
+ \ B:db\n\n
\n\n\nIt only supports full url lazy-loading: https://mermaid.js.org/config/icons.html\n\
+ \n\n\n
\narchitecture-beta\n\n group api(logos:aws-lambda)[API]\n\
+ \n\n\n service db(logos:aws-aurora)[Database] in api\n\n service disk1(logos:aws-glacier)[Storage]\
+ \ in api\n\n service disk2(logos:aws-s3)[Storage] in api\n\n service server(logos:aws-ec2)[Server]\
+ \ in api\n\n\n\n db:L -- R:server\n\n disk1:T -- B:server\n\n disk2:T --\
+ \ B:db\n\n
\n\n\n\n\nEnd of the file\n\n\n\n"
diff --git a/tests/test_markdown_mermaid/test_add_mermaid_script_and_tag_with_icons_input_file_path1_.yml b/tests/test_markdown_mermaid/test_add_mermaid_script_and_tag_with_icons_input_file_path1_.yml
new file mode 100644
index 0000000..c03aaeb
--- /dev/null
+++ b/tests/test_markdown_mermaid/test_add_mermaid_script_and_tag_with_icons_input_file_path1_.yml
@@ -0,0 +1,13 @@
+'# Title
+
+
+
+
+ Some text.
+
+
+
+
+ End of the file
+
+ '
diff --git a/uv.lock b/uv.lock
index 29bc4e3..9edc049 100644
--- a/uv.lock
+++ b/uv.lock
@@ -24,7 +24,7 @@ name = "bandit"
version = "1.7.10"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "colorama", marker = "platform_system == 'Windows'" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "pyyaml" },
{ name = "rich" },
{ name = "stevedore" },
@@ -158,7 +158,7 @@ name = "click"
version = "8.1.8"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "colorama", marker = "platform_system == 'Windows'" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
wheels = [
@@ -591,7 +591,7 @@ version = "1.6.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
- { name = "colorama", marker = "platform_system == 'Windows'" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "ghp-import" },
{ name = "importlib-metadata", marker = "python_full_version < '3.10'" },
{ name = "jinja2" },