#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Mermaid Diagram Renderer Finds mermaid code blocks in a markdown file and converts them to PNG images. """ import re import subprocess import os import sys from pathlib import Path def check_mmdc(): """Check if mermaid-cli (mmdc) is installed.""" try: subprocess.run(['mmdc', '--version'], check=True, capture_output=True) return True except (subprocess.CalledProcessError, FileNotFoundError): print("❌ 'mermaid-cli' (mmdc) not found.") print(" Please install it globally by running: npm install -g @mermaid-js/mermaid-cli") print(" You need Node.js and npm installed first.") return False def render_mermaid_diagrams(md_file_path, output_dir='charts'): """ Renders all mermaid diagrams in a markdown file to PNG images. The markdown file is updated in-place to link to the generated images. """ if not check_mmdc(): return False md_path = Path(md_file_path) if not md_path.exists(): print(f"❌ File not found: {md_file_path}") return False print(f"Processing Mermaid diagrams in: {md_path.name}") # Create charts directory if it doesn't exist charts_path = md_path.parent / output_dir charts_path.mkdir(exist_ok=True) with open(md_path, 'r', encoding='utf-8') as f: content = f.read() mermaid_blocks = re.findall(r'(```mermaid\n(.*?)\n```)', content, re.DOTALL) if not mermaid_blocks: print("No Mermaid diagrams found.") return True new_content = content for i, (block, code) in enumerate(mermaid_blocks): chart_filename = f"{md_path.stem}-mermaid-{i+1}.png" output_image_path = charts_path / chart_filename temp_mmd_path = charts_path / f"temp_{i}.mmd" # Write mermaid code to a temporary file with open(temp_mmd_path, 'w', encoding='utf-8') as f_temp: f_temp.write(code) # Run mmdc to convert to PNG try: cmd = [ 'mmdc', '-i', str(temp_mmd_path), '-o', str(output_image_path), '-b', 'transparent', # Transparent background '--configFile', 'mermaid_config.json' ] subprocess.run(cmd, check=True, capture_output=True) print(f" ✅ Rendered {output_image_path.name}") # Replace the mermaid block with an image link image_link = f"![Mermaid Chart]({output_dir}/{chart_filename})" new_content = new_content.replace(block, image_link, 1) except subprocess.CalledProcessError as e: print(f" ❌ Failed to render diagram {i+1}:") print(e.stderr.decode('utf-8', 'ignore')) finally: # Clean up temporary file if temp_mmd_path.exists(): os.remove(temp_mmd_path) # Write the updated content back to the markdown file with open(md_path, 'w', encoding='utf-8') as f: f.write(new_content) print(f"Updated {md_path.name} with image links.") return True def main(): """Main function to process all specified markdown files.""" markdown_files = [ 'rongzi_deepseek.md' ] all_successful = True for md_file in markdown_files: if not render_mermaid_diagrams(md_file): all_successful = False if not all_successful: sys.exit(1) if __name__ == '__main__': # This allows running the script on its own to process all relevant files main()