Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:08:14 +08:00
commit 6ea11d9f3a
6 changed files with 955 additions and 0 deletions

215
marp_to_pdf.py Executable file
View File

@@ -0,0 +1,215 @@
#!/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()