From technical-writer
Generates styled PDF books from directories of ordered markdown chapters using pandoc and weasyprint, with TOC, page numbers, and resolved inter-chapter links.
npx claudepluginhub sjungling/sjungling-claude-pluginsThis skill uses the workspace's default tool permissions.
Converts a directory of ordered markdown chapters into a single, styled PDF book with table of contents, page numbers, and resolved inter-chapter links.
Convert Markdown to professionally typeset PDFs using reportlab (primary) or pandoc+XeLaTeX (fallback). Handles CJK/Latin text, tables, code blocks, TOC, watermarks, themes for reports.
Generates professional PDF whitepapers from Markdown files using Typst templates, Pandoc, and custom fonts. Automatically installs dependencies via Bash, formats with typography hierarchy, and cleans up sources.
Converts markdown files, globs, or directories to professional PDFs with Obsidian-style preview using pandoc and wkhtmltopdf. Supports custom output directories and auto-installs tools.
Share bugs, ideas, or general feedback.
Converts a directory of ordered markdown chapters into a single, styled PDF book with table of contents, page numbers, and resolved inter-chapter links.
Core principle: The markdown files are the source of truth. The PDF is a derived artifact -- never edit the PDF directly.
Automatically activates when:
technical-overview or similar multi-chapter doc set is ready for exportThree tools must be installed before generation can proceed:
| Tool | Install command | Purpose |
|---|---|---|
pandoc | brew install pandoc | Markdown to HTML conversion |
weasyprint | uv tool install weasyprint | HTML to PDF rendering |
pango | brew install pango | Text layout (weasyprint dependency) |
Before running the script, verify availability:
command -v pandoc >/dev/null 2>&1 || echo "Missing: pandoc (brew install pandoc)"
command -v weasyprint >/dev/null 2>&1 || echo "Missing: weasyprint (uv tool install weasyprint)"
If either tool is missing, install it and retry. The script itself checks for dependencies and exits with a clear error message.
The generation pipeline has four stages:
README.md first, then 00-*.md through 99-*.md, then appendix-*.md.md links (e.g., [architecture](01-architecture.md)) are rewritten to internal #anchor links so they work within the single documentRun the generation script using $CLAUDE_PLUGIN_ROOT:
${CLAUDE_PLUGIN_ROOT}/skills/pdf-generation/scripts/generate-pdf.sh <input-dir> [output.pdf]
input-dir -- Directory containing the ordered markdown chaptersoutput.pdf -- Optional output path (defaults to <input-dir>/technical-overview.pdf)If $CLAUDE_PLUGIN_ROOT is not set (e.g., running outside a plugin context), locate the script manually:
# Fallback: find the script in the plugin installation directory
SCRIPT_PATH=$(find ~/.claude/plugins -path "*/pdf-generation/scripts/generate-pdf.sh" 2>/dev/null | head -1)
if [ -z "$SCRIPT_PATH" ]; then
echo "Error: generate-pdf.sh not found. Ensure the technical-writer plugin is installed."
exit 1
fi
"$SCRIPT_PATH" <input-dir> [output.pdf]
The input directory must contain ordered markdown files following this naming convention:
docs/technical-overview/
├── README.md # Title page and introduction (always first)
├── 00-getting-started.md # Numbered chapters in sequence
├── 01-architecture.md
├── 02-data-model.md
├── 03-api-reference.md
├── 04-deployment.md
├── appendix-a-glossary.md # Appendices after numbered chapters
└── appendix-b-faq.md
Expected output:
docs/technical-overview/
├── ... (source files unchanged)
└── technical-overview.pdf # Generated PDF (default output location)
The PDF includes:
# heading in README.md (or the directory name as fallback)For the PDF to have working internal links, the source markdown must follow these rules:
[architecture overview](01-architecture.md)[the store layer](03-data-layer.md#store)# heading -- this is used to resolve link targets.md links it cannot resolveCommon linking mistakes:
| Mistake | Fix |
|---|---|
Absolute paths (/docs/01-arch.md) | Use relative paths (01-arch.md) |
Missing # heading in chapter | Add exactly one h1 heading per chapter |
| Link to file not in input directory | Ensure all linked files are in the same directory |
The script embeds a print-optimized CSS stylesheet with sensible defaults:
For detailed CSS customization options (fonts, colors, page sizes, themes), see ./references/css-customization.md.
| Symptom | Cause | Fix |
|---|---|---|
| "Error: 'pandoc' is not installed" | Missing dependency | brew install pandoc |
| "Error: 'weasyprint' is not installed" | Missing dependency | uv tool install weasyprint && brew install pango |
Warning about unresolved .md links | Chapter heading does not match filename pattern | Ensure each chapter has a # heading and the link target filename is correct |
| PDF renders but fonts look wrong | Missing system fonts | weasyprint uses system fonts; install desired fonts via Font Book |
| Empty PDF or no chapters found | Files not matching naming convention | Verify files follow README.md, 00-*.md through 99-*.md, appendix-*.md pattern |
CLAUDE_PLUGIN_ROOT is empty | Running outside plugin context | Use the fallback script discovery method described above |
| Long code blocks overflow margins | Default CSS handles this | Verify overflow-wrap: break-word and white-space: pre-wrap in CSS |
./references/css-customization.md -- Detailed CSS customization options for fonts, page sizes, colors, and themes./scripts/generate-pdf.sh -- The generation script (inspect for advanced modification)