pdf-creator: 自动 DYLD_LIBRARY_PATH + 列表渲染修复 + CSS 改进
- macOS ARM Homebrew 库路径自动检测(不再需要手动 export) - 添加 markdown 预处理器:确保列表前有空行,防止解析为段落文本 - CSS word-break: break-all → overflow-wrap: break-word(中英混排友好) - batch_convert.py: 修复跨目录运行时的 import 路径 - SKILL.md: 移除手动环境变量步骤 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ Create professional PDF documents from markdown with proper Chinese font support
|
||||
Convert a single markdown file:
|
||||
|
||||
```bash
|
||||
cd ~/workspace/claude-code-skills/pdf-creator
|
||||
uv run --with weasyprint --with markdown scripts/md_to_pdf.py input.md output.pdf
|
||||
```
|
||||
|
||||
@@ -21,14 +22,7 @@ Batch convert multiple files:
|
||||
uv run --with weasyprint --with markdown scripts/batch_convert.py *.md --output-dir ./pdfs
|
||||
```
|
||||
|
||||
## macOS Environment Setup
|
||||
|
||||
If encountering library errors, set these environment variables first:
|
||||
|
||||
```bash
|
||||
export DYLD_LIBRARY_PATH="/opt/homebrew/lib:$DYLD_LIBRARY_PATH"
|
||||
export PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
```
|
||||
macOS ARM (Homebrew) 的 `DYLD_LIBRARY_PATH` 会自动检测配置,无需手动设置。
|
||||
|
||||
## Font Configuration
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
from md_to_pdf import markdown_to_pdf
|
||||
|
||||
|
||||
|
||||
@@ -16,9 +16,20 @@ Requirements:
|
||||
export DYLD_LIBRARY_PATH="/opt/homebrew/lib:$DYLD_LIBRARY_PATH"
|
||||
"""
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Auto-configure library path on macOS ARM (Homebrew) — must be before weasyprint import
|
||||
if platform.system() == 'Darwin':
|
||||
_homebrew_lib = '/opt/homebrew/lib'
|
||||
if Path(_homebrew_lib).is_dir():
|
||||
_cur = os.environ.get('DYLD_LIBRARY_PATH', '')
|
||||
if _homebrew_lib not in _cur:
|
||||
os.environ['DYLD_LIBRARY_PATH'] = f"{_homebrew_lib}:{_cur}" if _cur else _homebrew_lib
|
||||
|
||||
import markdown
|
||||
from weasyprint import CSS, HTML
|
||||
|
||||
@@ -89,8 +100,8 @@ th, td {
|
||||
border: 1px solid #666;
|
||||
padding: 8px 6px;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
th {
|
||||
@@ -134,6 +145,24 @@ blockquote {
|
||||
"""
|
||||
|
||||
|
||||
def _ensure_list_spacing(text: str) -> str:
|
||||
"""Ensure blank lines before list items for proper markdown parsing.
|
||||
|
||||
The Python markdown library requires a blank line before a list when it
|
||||
follows a paragraph. Without it, list items render as plain text.
|
||||
"""
|
||||
lines = text.split('\n')
|
||||
result = []
|
||||
list_re = re.compile(r'^(\s*)([-*+]|\d+\.)\s')
|
||||
for i, line in enumerate(lines):
|
||||
if i > 0 and list_re.match(line):
|
||||
prev = lines[i - 1]
|
||||
if prev.strip() and not list_re.match(prev):
|
||||
result.append('')
|
||||
result.append(line)
|
||||
return '\n'.join(result)
|
||||
|
||||
|
||||
def markdown_to_pdf(md_file: str, pdf_file: str | None = None) -> str:
|
||||
"""
|
||||
Convert markdown file to PDF with Chinese font support.
|
||||
@@ -150,8 +179,8 @@ def markdown_to_pdf(md_file: str, pdf_file: str | None = None) -> str:
|
||||
if pdf_file is None:
|
||||
pdf_file = str(md_path.with_suffix('.pdf'))
|
||||
|
||||
# Read markdown content
|
||||
md_content = md_path.read_text(encoding='utf-8')
|
||||
# Read and preprocess markdown content
|
||||
md_content = _ensure_list_spacing(md_path.read_text(encoding='utf-8'))
|
||||
|
||||
# Convert to HTML
|
||||
html_content = markdown.markdown(
|
||||
|
||||
Reference in New Issue
Block a user