|
|
|
|
|
import re |
|
|
import os |
|
|
import sys |
|
|
import subprocess |
|
|
from pathlib import Path |
|
|
|
|
|
def process_mermaid_diagrams(content, file_dir): |
|
|
"""Convert mermaid diagrams to images""" |
|
|
mermaid_pattern = r'```mermaid\n(.*?)\n```' |
|
|
|
|
|
def replace_mermaid(match): |
|
|
mermaid_code = match.group(1) |
|
|
|
|
|
diagram_hash = str(abs(hash(mermaid_code))) |
|
|
mermaid_file = f"{file_dir}/mermaid_{diagram_hash}.mmd" |
|
|
svg_file = f"{file_dir}/mermaid_{diagram_hash}.svg" |
|
|
png_file = f"{file_dir}/mermaid_{diagram_hash}.png" |
|
|
|
|
|
|
|
|
try: |
|
|
with open(mermaid_file, 'w', encoding='utf-8') as f: |
|
|
f.write(mermaid_code) |
|
|
except Exception as e: |
|
|
print(f"Error writing mermaid file: {e}") |
|
|
return f'\n```\n{mermaid_code}\n```\n' |
|
|
|
|
|
try: |
|
|
|
|
|
config_file = os.path.join(file_dir, '..', '..', '.github', 'workflows', 'puppeteer-config.json') |
|
|
if os.path.exists(config_file): |
|
|
result = subprocess.run([ |
|
|
'mmdc', '-i', mermaid_file, '-o', svg_file, |
|
|
'--theme', 'default', '--backgroundColor', 'white', |
|
|
'--configFile', config_file, |
|
|
'--puppeteerConfig', config_file |
|
|
], check=True, capture_output=True, text=True, timeout=60) |
|
|
else: |
|
|
|
|
|
result = subprocess.run([ |
|
|
'mmdc', '-i', mermaid_file, '-o', svg_file, |
|
|
'--theme', 'default', '--backgroundColor', 'white', |
|
|
'--puppeteerConfig', '{"args": ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--disable-gpu", "--single-process"]}' |
|
|
], check=True, capture_output=True, text=True, timeout=60) |
|
|
|
|
|
|
|
|
subprocess.run([ |
|
|
'rsvg-convert', '-f', 'png', '-o', png_file, |
|
|
'--width', '1200', '--height', '800', svg_file |
|
|
], check=True, capture_output=True, text=True) |
|
|
|
|
|
|
|
|
try: |
|
|
os.remove(mermaid_file) |
|
|
if os.path.exists(svg_file): |
|
|
os.remove(svg_file) |
|
|
except: |
|
|
pass |
|
|
|
|
|
|
|
|
return ( |
|
|
f'\n<div class="mermaid-container">\n\n' |
|
|
f'})\n\n' |
|
|
f'</div>\n' |
|
|
) |
|
|
|
|
|
except subprocess.CalledProcessError as e: |
|
|
print(f"Error converting mermaid diagram: {e}") |
|
|
print(f"Command output: {e.stderr if e.stderr else 'No stderr'}") |
|
|
|
|
|
|
|
|
try: |
|
|
print("Trying basic mmdc command...") |
|
|
subprocess.run([ |
|
|
'mmdc', '-i', mermaid_file, '-o', svg_file, |
|
|
'--puppeteerConfig', '{"args": ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--disable-gpu", "--single-process"]}' |
|
|
], check=True, capture_output=True, text=True, timeout=60) |
|
|
|
|
|
|
|
|
subprocess.run([ |
|
|
'rsvg-convert', '-f', 'png', '-o', png_file, |
|
|
'--width', '1200', '--height', '800', svg_file |
|
|
], check=True, capture_output=True, text=True) |
|
|
|
|
|
|
|
|
try: |
|
|
os.remove(mermaid_file) |
|
|
if os.path.exists(svg_file): |
|
|
os.remove(svg_file) |
|
|
except: |
|
|
pass |
|
|
|
|
|
return ( |
|
|
f'\n<div class="mermaid-container">\n\n' |
|
|
f'})\n\n' |
|
|
f'</div>\n' |
|
|
) |
|
|
|
|
|
except subprocess.CalledProcessError as e2: |
|
|
print(f"Basic mmdc also failed: {e2}") |
|
|
try: |
|
|
os.remove(mermaid_file) |
|
|
except: |
|
|
pass |
|
|
|
|
|
|
|
|
print("All Mermaid rendering methods failed, keeping original code") |
|
|
return f'\n```mermaid\n{mermaid_code}\n```\n' |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Unexpected error with mermaid: {e}") |
|
|
try: |
|
|
os.remove(mermaid_file) |
|
|
except: |
|
|
pass |
|
|
return f'\n```mermaid\n{mermaid_code}\n```\n' |
|
|
|
|
|
return re.sub(mermaid_pattern, replace_mermaid, content, flags=re.DOTALL) |
|
|
|
|
|
|
|
|
def clean_emojis_and_fix_images(content, file_dir): |
|
|
"""Remove/replace emojis and fix image paths""" |
|
|
emoji_replacements = { |
|
|
'π΅': '[Audio]', |
|
|
'π¬': '[Video]', |
|
|
'π': '[Document]', |
|
|
'π': '[Analytics]', |
|
|
'π§ ': '[AI]', |
|
|
'π₯': '[Media]', |
|
|
'π': '[File]', |
|
|
'β
': '[Success]', |
|
|
'β': '[Failed]' |
|
|
} |
|
|
|
|
|
for emoji, replacement in emoji_replacements.items(): |
|
|
content = content.replace(emoji, replacement) |
|
|
|
|
|
|
|
|
img_pattern = r'!\[([^\]]*)\]\(([^)]+)\)' |
|
|
|
|
|
def replace_image(match): |
|
|
alt_text = match.group(1) |
|
|
img_path = match.group(2) |
|
|
|
|
|
if not img_path.startswith(('http://', 'https://', '/')): |
|
|
abs_img_path = os.path.join(file_dir, img_path) |
|
|
if os.path.exists(abs_img_path): |
|
|
img_path = os.path.relpath(abs_img_path, file_dir) |
|
|
|
|
|
return ( |
|
|
f'<img src="{img_path}" alt="{alt_text}" ' |
|
|
f'style="max-width: 100%; height: auto; display: block; margin: 1em auto;" />' |
|
|
) |
|
|
|
|
|
content = re.sub(img_pattern, replace_image, content) |
|
|
|
|
|
|
|
|
content = re.sub( |
|
|
r'<img\s+([^>]*?)\s*/?>', |
|
|
lambda m: ( |
|
|
f'<img {m.group(1)} ' |
|
|
f'style="max-width: 100%; height: auto; display: block; margin: 1em auto;" />' |
|
|
), |
|
|
content |
|
|
) |
|
|
|
|
|
return content |
|
|
|
|
|
def main(): |
|
|
if len(sys.argv) != 2: |
|
|
print("Usage: python preprocess_markdown.py <markdown_file>") |
|
|
sys.exit(1) |
|
|
|
|
|
md_file = sys.argv[1] |
|
|
|
|
|
if not os.path.exists(md_file): |
|
|
print(f"Error: File {md_file} does not exist") |
|
|
sys.exit(1) |
|
|
|
|
|
try: |
|
|
file_dir = os.path.dirname(os.path.abspath(md_file)) |
|
|
|
|
|
with open(md_file, 'r', encoding='utf-8') as f: |
|
|
content = f.read() |
|
|
|
|
|
print(f"Processing file: {md_file}") |
|
|
print(f"File directory: {file_dir}") |
|
|
print(f"Content length: {len(content)} characters") |
|
|
|
|
|
|
|
|
content = process_mermaid_diagrams(content, file_dir) |
|
|
print(f"Mermaid processing complete. Content length: {len(content)}") |
|
|
|
|
|
|
|
|
content = clean_emojis_and_fix_images(content, file_dir) |
|
|
print(f"Image path fixing complete. Content length: {len(content)}") |
|
|
|
|
|
|
|
|
processed_file = md_file.replace('.md', '_processed.md') |
|
|
with open(processed_file, 'w', encoding='utf-8') as f: |
|
|
f.write(content) |
|
|
|
|
|
print(f"Processed file saved as: {processed_file}") |
|
|
print(processed_file) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Error processing {md_file}: {e}") |
|
|
import traceback |
|
|
traceback.print_exc() |
|
|
sys.exit(1) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |