#!/usr/bin/env python3 """ Marp Markdown to PDF Converter Converts Markdown files to beautiful presentation PDFs using Marp CLI. """ import sys import os import subprocess import shutil from pathlib import Path import argparse def check_marp_cli(): """Check if Marp CLI is installed.""" # Try marp-cli if shutil.which('marp'): return 'marp' # Try npx if shutil.which('npx'): try: result = subprocess.run( ['npx', '@marp-team/marp-cli', '--version'], capture_output=True, text=True, timeout=10 ) if result.returncode == 0: return 'npx' except: pass return None def install_instructions(): """Print installation instructions.""" print("\n❌ Marp CLI not found!") print("\n请安装Marp CLI:") print("\n方法1: 使用npm全局安装") print(" npm install -g @marp-team/marp-cli") print("\n方法2: 使用npx (无需安装)") print(" npx @marp-team/marp-cli --version") print("\n方法3: 使用Homebrew (macOS)") print(" brew install marp-cli") print() def convert_markdown_to_pdf(input_file, output_file=None, theme='default', html_output=False): """Convert Markdown to PDF using Marp.""" # Validate input file if not os.path.exists(input_file): print(f"❌ 错误: 输入文件 '{input_file}' 不存在!") return False # Check Marp CLI marp_cmd = check_marp_cli() if not marp_cmd: install_instructions() return False # Determine output file if output_file is None: output_file = Path(input_file).with_suffix('.pdf') print("=" * 70) print("Marp Markdown转PDF工具") print("=" * 70) print(f"\n📄 转换Markdown为演示文稿PDF") print(f" 输入: {input_file}") print(f" 输出: {output_file}") print(f" 主题: {theme}\n") try: # Build Marp command if marp_cmd == 'marp': cmd = ['marp'] else: # npx cmd = ['npx', '@marp-team/marp-cli'] cmd.extend([ input_file, '--pdf', '--allow-local-files', '--theme', theme, '-o', str(output_file) ]) # Run Marp conversion print("⏳ 生成PDF...") result = subprocess.run( cmd, capture_output=True, text=True, timeout=60 ) if result.returncode != 0: print(f"❌ 转换失败!") print(f"错误信息: {result.stderr}") return False # Get file size if os.path.exists(output_file): size_kb = os.path.getsize(output_file) / 1024 print(f"\n✅ 成功生成PDF!") print(f" 大小: {size_kb:.1f} KB") # Generate HTML if requested if html_output: html_file = Path(output_file).with_suffix('.html') print(f"\n📄 生成HTML版本...") html_cmd = cmd.copy() # Remove --pdf and change output html_cmd = [c for c in html_cmd if c != '--pdf'] html_cmd[-1] = str(html_file) result = subprocess.run( html_cmd, capture_output=True, text=True, timeout=60 ) if result.returncode == 0 and os.path.exists(html_file): html_size_kb = os.path.getsize(html_file) / 1024 print(f"✅ HTML生成成功!") print(f" 大小: {html_size_kb:.1f} KB") print(f"\n💡 打开查看:") print(f" PDF: open {output_file}") print(f" HTML: open {html_file}") else: print(f"\n💡 打开查看:") print(f" PDF: open {output_file}") else: print(f"\n💡 打开查看:") print(f" open {output_file}") return True except subprocess.TimeoutExpired: print("\n❌ 转换超时!") return False except Exception as e: print(f"\n❌ 转换失败: {str(e)}") import traceback traceback.print_exc() return False def ensure_marp_frontmatter(input_file): """Check if Markdown has Marp frontmatter, add if missing.""" with open(input_file, 'r', encoding='utf-8') as f: content = f.read() # Check if already has marp frontmatter if content.startswith('---\nmarp:') or 'marp: true' in content[:100]: return False # Already has frontmatter # Add Marp frontmatter frontmatter = """--- marp: true theme: default paginate: true --- """ with open(input_file, 'w', encoding='utf-8') as f: f.write(frontmatter + content) return True # Added frontmatter def main(): """Main entry point.""" parser = argparse.ArgumentParser( description='Convert Markdown to PDF presentation using Marp' ) parser.add_argument('input', help='Input Markdown file') parser.add_argument('output', nargs='?', help='Output PDF file (optional)') parser.add_argument( '--theme', choices=['default', 'gaia', 'uncover'], default='default', help='Marp theme to use' ) parser.add_argument( '--html', action='store_true', help='Also generate HTML output' ) parser.add_argument( '--add-frontmatter', action='store_true', help='Add Marp frontmatter if missing' ) args = parser.parse_args() # Add frontmatter if requested if args.add_frontmatter: if ensure_marp_frontmatter(args.input): print("✅ 已添加Marp前置元数据\n") success = convert_markdown_to_pdf( args.input, args.output, args.theme, args.html ) sys.exit(0 if success else 1) if __name__ == '__main__': main()