From ec3141b8ef7f211b0f8e00bc9a80d4dbaea6bf54 Mon Sep 17 00:00:00 2001 From: daymade Date: Thu, 11 Dec 2025 20:04:33 +0800 Subject: [PATCH] feat: Add pdf-creator skill for markdown to PDF conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .claude-plugin/marketplace.json | 14 +- pdf-creator/.security-scan-passed | 4 + pdf-creator/SKILL.md | 61 +++++++++ pdf-creator/scripts/batch_convert.py | 78 +++++++++++ pdf-creator/scripts/md_to_pdf.py | 198 +++++++++++++++++++++++++++ 5 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 pdf-creator/.security-scan-passed create mode 100644 pdf-creator/SKILL.md create mode 100644 pdf-creator/scripts/batch_convert.py create mode 100644 pdf-creator/scripts/md_to_pdf.py diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 30c17a4..ba3c80c 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,8 +5,8 @@ "email": "daymadev89@gmail.com" }, "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", - "version": "1.13.0", + "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.14.0", "homepage": "https://github.com/daymade/claude-code-skills" }, "plugins": [ @@ -209,6 +209,16 @@ "category": "productivity", "keywords": ["documentation", "cleanup", "consolidation", "redundancy", "merge", "docs"], "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"] } ] } diff --git a/pdf-creator/.security-scan-passed b/pdf-creator/.security-scan-passed new file mode 100644 index 0000000..3e23e8c --- /dev/null +++ b/pdf-creator/.security-scan-passed @@ -0,0 +1,4 @@ +Security scan passed +Scanned at: 2025-12-11T19:59:37.734920 +Tool: gitleaks + pattern-based validation +Content hash: a9abbfd8a9175fbbdad11e86ce7691c080614982d9b37ffa2b7610bbfad03377 diff --git a/pdf-creator/SKILL.md b/pdf-creator/SKILL.md new file mode 100644 index 0000000..c369752 --- /dev/null +++ b/pdf-creator/SKILL.md @@ -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 diff --git a/pdf-creator/scripts/batch_convert.py b/pdf-creator/scripts/batch_convert.py new file mode 100644 index 0000000..9eaa37f --- /dev/null +++ b/pdf-creator/scripts/batch_convert.py @@ -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() diff --git a/pdf-creator/scripts/md_to_pdf.py b/pdf-creator/scripts/md_to_pdf.py new file mode 100644 index 0000000..796bb75 --- /dev/null +++ b/pdf-creator/scripts/md_to_pdf.py @@ -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""" + + + + {md_path.stem} + + +{html_content} + +""" + + # 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 [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()