feat: Add pdf-creator skill for markdown to PDF conversion
- Add pdf-creator skill with Chinese font support (weasyprint) - Include md_to_pdf.py for single file conversion - Include batch_convert.py for multiple files - Support formal documents: legal filings, reports, trademark applications - Update marketplace to v1.14.0 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,8 @@
|
|||||||
"email": "daymadev89@gmail.com"
|
"email": "daymadev89@gmail.com"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"description": "Professional Claude Code skills for GitHub operations, document conversion, diagram generation, statusline customization, Teams communication, repomix utilities, skill creation, CLI demo generation, LLM icon access, Cloudflare troubleshooting, UI design system extraction, professional presentation creation, YouTube video downloading, secure repomix packaging, ASR transcription correction, video comparison quality analysis, comprehensive QA testing infrastructure, prompt optimization with EARS methodology, session history recovery, and documentation cleanup",
|
"description": "Professional Claude Code skills for GitHub operations, document conversion, diagram generation, statusline customization, Teams communication, repomix utilities, skill creation, CLI demo generation, LLM icon access, Cloudflare troubleshooting, UI design system extraction, professional presentation creation, YouTube video downloading, secure repomix packaging, ASR transcription correction, video comparison quality analysis, comprehensive QA testing infrastructure, prompt optimization with EARS methodology, session history recovery, documentation cleanup, and PDF generation with Chinese font support",
|
||||||
"version": "1.13.0",
|
"version": "1.14.0",
|
||||||
"homepage": "https://github.com/daymade/claude-code-skills"
|
"homepage": "https://github.com/daymade/claude-code-skills"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
@@ -209,6 +209,16 @@
|
|||||||
"category": "productivity",
|
"category": "productivity",
|
||||||
"keywords": ["documentation", "cleanup", "consolidation", "redundancy", "merge", "docs"],
|
"keywords": ["documentation", "cleanup", "consolidation", "redundancy", "merge", "docs"],
|
||||||
"skills": ["./docs-cleaner"]
|
"skills": ["./docs-cleaner"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pdf-creator",
|
||||||
|
"description": "Create PDF documents from markdown with proper Chinese font support using weasyprint. Use when converting markdown to PDF, generating formal documents (legal filings, trademark applications, reports), or when Chinese typography is required. Triggers include convert to PDF, generate PDF, markdown to PDF, or printable documents",
|
||||||
|
"source": "./",
|
||||||
|
"strict": false,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"category": "document-conversion",
|
||||||
|
"keywords": ["pdf", "markdown", "weasyprint", "chinese-fonts", "document-generation", "legal", "reports", "typography"],
|
||||||
|
"skills": ["./pdf-creator"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
4
pdf-creator/.security-scan-passed
Normal file
4
pdf-creator/.security-scan-passed
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Security scan passed
|
||||||
|
Scanned at: 2025-12-11T19:59:37.734920
|
||||||
|
Tool: gitleaks + pattern-based validation
|
||||||
|
Content hash: a9abbfd8a9175fbbdad11e86ce7691c080614982d9b37ffa2b7610bbfad03377
|
||||||
61
pdf-creator/SKILL.md
Normal file
61
pdf-creator/SKILL.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
name: pdf-creator
|
||||||
|
description: Create PDF documents from markdown with proper Chinese font support using weasyprint. This skill should be used when converting markdown to PDF, generating formal documents (legal, trademark filings, reports), or when Chinese typography is required. Triggers include "convert to PDF", "generate PDF", "markdown to PDF", or any request for creating printable documents.
|
||||||
|
---
|
||||||
|
|
||||||
|
# PDF Creator
|
||||||
|
|
||||||
|
Create professional PDF documents from markdown with proper Chinese font support.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
Convert a single markdown file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run --with weasyprint --with markdown scripts/md_to_pdf.py input.md output.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
Batch convert multiple files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Font Configuration
|
||||||
|
|
||||||
|
The scripts use these Chinese fonts (with fallbacks):
|
||||||
|
|
||||||
|
| Font Type | Primary | Fallbacks |
|
||||||
|
|-----------|---------|-----------|
|
||||||
|
| Body text | Songti SC | SimSun, STSong, Noto Serif CJK SC |
|
||||||
|
| Headings | Heiti SC | SimHei, STHeiti, Noto Sans CJK SC |
|
||||||
|
|
||||||
|
## Output Specifications
|
||||||
|
|
||||||
|
- **Page size**: A4
|
||||||
|
- **Margins**: 2.5cm top/bottom, 2cm left/right
|
||||||
|
- **Body font**: 12pt, 1.8 line height
|
||||||
|
- **Max file size**: Designed to stay under 2MB for form submissions
|
||||||
|
|
||||||
|
## Common Use Cases
|
||||||
|
|
||||||
|
1. **Legal documents**: Trademark filings, contracts, evidence lists
|
||||||
|
2. **Reports**: Business reports, technical documentation
|
||||||
|
3. **Formal letters**: Official correspondence requiring print format
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Problem**: Chinese characters display as boxes
|
||||||
|
**Solution**: Ensure Songti SC or other Chinese fonts are installed on the system
|
||||||
|
|
||||||
|
**Problem**: `weasyprint` import error
|
||||||
|
**Solution**: Run with `uv run --with weasyprint --with markdown` to ensure dependencies
|
||||||
78
pdf-creator/scripts/batch_convert.py
Normal file
78
pdf-creator/scripts/batch_convert.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Batch convert multiple markdown files to PDF.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python batch_convert.py file1.md file2.md file3.md
|
||||||
|
python batch_convert.py *.md
|
||||||
|
python batch_convert.py --output-dir ./pdfs file1.md file2.md
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
pip install weasyprint markdown
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from md_to_pdf import markdown_to_pdf
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Batch convert markdown files to PDF with Chinese font support'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'files',
|
||||||
|
nargs='+',
|
||||||
|
help='Markdown files to convert'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--output-dir', '-o',
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help='Output directory for PDFs (default: same as input)'
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
output_dir = Path(args.output_dir) if args.output_dir else None
|
||||||
|
if output_dir:
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
success = 0
|
||||||
|
failed = 0
|
||||||
|
|
||||||
|
for md_file in args.files:
|
||||||
|
md_path = Path(md_file)
|
||||||
|
|
||||||
|
if not md_path.exists():
|
||||||
|
print(f"[SKIP] File not found: {md_file}")
|
||||||
|
failed += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not md_path.suffix.lower() == '.md':
|
||||||
|
print(f"[SKIP] Not a markdown file: {md_file}")
|
||||||
|
failed += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Determine output path
|
||||||
|
if output_dir:
|
||||||
|
pdf_file = str(output_dir / md_path.with_suffix('.pdf').name)
|
||||||
|
else:
|
||||||
|
pdf_file = str(md_path.with_suffix('.pdf'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(f"Converting: {md_file} -> {pdf_file}")
|
||||||
|
markdown_to_pdf(str(md_path), pdf_file)
|
||||||
|
success += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Failed to convert {md_file}: {e}")
|
||||||
|
failed += 1
|
||||||
|
|
||||||
|
print(f"\nCompleted: {success} succeeded, {failed} failed")
|
||||||
|
sys.exit(0 if failed == 0 else 1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
198
pdf-creator/scripts/md_to_pdf.py
Normal file
198
pdf-creator/scripts/md_to_pdf.py
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Markdown to PDF converter with Chinese font support.
|
||||||
|
|
||||||
|
Converts markdown files to PDF using weasyprint, with proper Chinese typography.
|
||||||
|
Designed for formal documents (trademark filings, legal documents, reports).
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python md_to_pdf.py input.md output.pdf
|
||||||
|
python md_to_pdf.py input.md # outputs input.pdf
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
pip install weasyprint markdown
|
||||||
|
|
||||||
|
macOS environment setup (if needed):
|
||||||
|
export DYLD_LIBRARY_PATH="/opt/homebrew/lib:$DYLD_LIBRARY_PATH"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import markdown
|
||||||
|
from weasyprint import CSS, HTML
|
||||||
|
|
||||||
|
|
||||||
|
# CSS with Chinese font support
|
||||||
|
CSS_STYLES = """
|
||||||
|
@page {
|
||||||
|
size: A4;
|
||||||
|
margin: 2.5cm 2cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Songti SC', 'SimSun', 'STSong', 'Noto Serif CJK SC', serif;
|
||||||
|
font-size: 12pt;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #000;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: 'Heiti SC', 'SimHei', 'STHeiti', 'Noto Sans CJK SC', sans-serif;
|
||||||
|
font-size: 18pt;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family: 'Heiti SC', 'SimHei', 'STHeiti', 'Noto Sans CJK SC', sans-serif;
|
||||||
|
font-size: 14pt;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-family: 'Heiti SC', 'SimHei', 'STHeiti', 'Noto Sans CJK SC', sans-serif;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.8em 0;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
margin: 0.8em 0;
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0.4em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
margin: 1em 0;
|
||||||
|
font-size: 10pt;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #666;
|
||||||
|
padding: 8px 6px;
|
||||||
|
text-align: left;
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
margin: 1.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: 'SF Mono', 'Monaco', 'Menlo', monospace;
|
||||||
|
font-size: 10pt;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 0.2em 0.4em;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 1em;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-size: 10pt;
|
||||||
|
line-height: 1.4;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid #ccc;
|
||||||
|
margin: 1em 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def markdown_to_pdf(md_file: str, pdf_file: str | None = None) -> str:
|
||||||
|
"""
|
||||||
|
Convert markdown file to PDF with Chinese font support.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
md_file: Path to input markdown file
|
||||||
|
pdf_file: Path to output PDF file (optional, defaults to same name as input)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Path to generated PDF file
|
||||||
|
"""
|
||||||
|
md_path = Path(md_file)
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
|
# Convert to HTML
|
||||||
|
html_content = markdown.markdown(
|
||||||
|
md_content,
|
||||||
|
extensions=['tables', 'fenced_code', 'codehilite', 'toc']
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create full HTML document
|
||||||
|
full_html = f"""<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{md_path.stem}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{html_content}
|
||||||
|
</body>
|
||||||
|
</html>"""
|
||||||
|
|
||||||
|
# Generate PDF
|
||||||
|
HTML(string=full_html).write_pdf(pdf_file, stylesheets=[CSS(string=CSS_STYLES)])
|
||||||
|
|
||||||
|
return pdf_file
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python md_to_pdf.py <input.md> [output.pdf]")
|
||||||
|
print("\nConverts markdown to PDF with Chinese font support.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
md_file = sys.argv[1]
|
||||||
|
pdf_file = sys.argv[2] if len(sys.argv) > 2 else None
|
||||||
|
|
||||||
|
if not Path(md_file).exists():
|
||||||
|
print(f"Error: File not found: {md_file}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
output = markdown_to_pdf(md_file, pdf_file)
|
||||||
|
print(f"Generated: {output}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user