#!/usr/bin/env python3 """ 批量将 Markdown 转为 PDF —— 通过 Google Chrome Headless 浏览器渲染 1. Markdown → HTML(含代码高亮、表格样式) 2. HTML → 写入临时文件 → Chrome --headless --print-to-pdf """ import glob import os import subprocess import tempfile import markdown from markdown.extensions.tables import TableExtension from markdown.extensions.fenced_code import FencedCodeExtension from markdown.extensions.codehilite import CodeHiliteExtension from markdown.extensions.toc import TocExtension # ─── 配置 ─── BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DIRS = [f"{i:02d}-*" for i in range(1, 14)] PATTERNS = ["*-鉴别材料.md", "*-源程序.md"] CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" CSS = """ @page { size: A4; margin: 20mm 18mm 20mm 18mm; } body { font-family: "PingFang SC", "Microsoft YaHei", "STSong", "Noto Sans CJK SC", sans-serif; font-size: 11pt; line-height: 1.7; color: #222; max-width: 100%; padding: 0 10px; margin: 0; } h1 { font-size: 20pt; border-bottom: 2px solid #333; padding-bottom: 6px; margin-top: 24pt; } h2 { font-size: 16pt; border-bottom: 1px solid #999; padding-bottom: 4px; margin-top: 20pt; } h3 { font-size: 13pt; margin-top: 16pt; } h4 { font-size: 12pt; margin-top: 12pt; } table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 10pt; page-break-inside: auto; } th, td { border: 1px solid #bbb; padding: 6px 10px; text-align: left; } th { background-color: #f0f0f0; font-weight: bold; } tr:nth-child(even) { background-color: #fafafa; } code { font-family: "SF Mono", "Menlo", "Consolas", "Monaco", monospace; font-size: 9.5pt; background: #f5f5f5; padding: 1px 4px; border-radius: 3px; } pre { background: #f6f8fa; border: 1px solid #e1e4e8; border-radius: 6px; padding: 12px 16px; overflow-x: auto; font-size: 8.5pt; line-height: 1.5; page-break-inside: auto; white-space: pre-wrap; word-wrap: break-word; } pre code { background: transparent; padding: 0; font-size: inherit; } blockquote { border-left: 4px solid #dfe2e5; padding: 4px 16px; margin: 12px 0; color: #555; background: #f9f9f9; } img { max-width: 100%; } hr { border: none; border-top: 1px solid #ddd; margin: 20px 0; } .codehilite { background: #f6f8fa; border-radius: 6px; padding: 12px 16px; } """ def md_to_html(md_path): """将 Markdown 文件转换为完整的 HTML 页面""" with open(md_path, 'r', encoding='utf-8') as f: md_text = f.read() extensions = [ TableExtension(), FencedCodeExtension(), CodeHiliteExtension(css_class='codehilite', guess_lang=False), TocExtension(permalink=False), ] html_body = markdown.markdown(md_text, extensions=extensions) title = os.path.splitext(os.path.basename(md_path))[0] html = f"""