111 lines
3.5 KiB
Python
111 lines
3.5 KiB
Python
#!/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""
|
|
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()
|