mermaidを画像にするPythonスクリプト

Obsidianを使っています。また、mermaidを使って図を書くこともよくあります。

書いた図を画像で出力したいことも割とあります。
というわけで、先日markdownファイルを指定したら、画像で出力するPythonスクリプトを書きました。書いたのはAIで私はレビューとか指示出しだけです。

書き捨てのコードのつもりで書いたのですが、割と頻繁に使うスクリプトになってきたので、とりあえずブログでも公開しておきます。気が向いたら、GitHubに公開してコマンドラインツールにします。

メモ:個人マシンだと、2026/05/20 あたりの作業フォルダに入ってます。

#!/usr/bin/env python3
# mermaid_to_image.py

import re
import subprocess
import sys
from pathlib import Path
import tempfile


def extract_mermaid_blocks(markdown_text):
    """Markdownからmermaidコードブロックを抽出"""
    pattern = r"```mermaid\n(.*?)\n```"
    return re.findall(pattern, markdown_text, re.DOTALL)


def convert_to_image(mermaid_code, output_path):
    """mermaidコードを画像に変換"""
    with tempfile.NamedTemporaryFile(
        mode="w", suffix=".mmd", delete=False, encoding="utf-8"
    ) as f:
        f.write(mermaid_code)
        tmp_path = f.name

    try:
        result = subprocess.run(
            ["mmdc", "-i", tmp_path, "-o", str(output_path), "-b", "white"],
            capture_output=True,
            text=True,
        )
        if result.returncode != 0:
            print(f"エラー: {result.stderr}")
            return False
        return True
    finally:
        Path(tmp_path).unlink(missing_ok=True)


def process_file(input_path, output_dir, format="png"):
    """ファイルを処理(.mmd または .md)"""
    input_path = Path(input_path)
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    if input_path.suffix == ".mmd":
        # .mmdファイルを直接変換
        output_path = output_dir / f"{input_path.stem}.{format}"
        if convert_to_image(input_path.read_text(encoding="utf-8"), output_path):
            print(f"✓ {output_path}")

    elif input_path.suffix == ".md":
        # Markdown内のmermaidブロックを変換
        content = input_path.read_text(encoding="utf-8")
        blocks = extract_mermaid_blocks(content)

        for i, block in enumerate(blocks, 1):
            output_path = output_dir / f"{input_path.stem}_diagram_{i}.{format}"
            if convert_to_image(block, output_path):
                print(f"✓ {output_path}")

    else:
        print(f"エラー: 未対応の拡張子です ({input_path.suffix})。.mmd または .md を指定してください。")
        sys.exit(1)


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(
            "使い方: python mermaid_to_image.py <入力ファイル> [出力ディレクトリ] [形式]"
        )
        print("例: python mermaid_to_image.py diagram.mmd ./images png")
        sys.exit(1)

    input_path = sys.argv[1]
    output_dir = sys.argv[2] if len(sys.argv) > 2 else "./images"
    format = sys.argv[3] if len(sys.argv) > 3 else "png"

    process_file(input_path, output_dir, format)
Code language: PHP (php)

類似投稿