SKILL.md
$27
Single Source of Truth Pattern
This skill provides production-proven assets in ${CLAUDE_PLUGIN_ROOT}/skills/pandoc-pdf-generation/assets/:
table-spacing-template.tex- Production-tuned LaTeX preamble (booktabs, colortbl, ToC fixes)
build-pdf.sh- Universal auto-detecting build script
From Any Project
/usr/bin/env bash << 'DETECT_EOF'
# Create symlink once per project (git-friendly)
ln -s ${CLAUDE_PLUGIN_ROOT}/skills/pandoc-pdf-generation/assets/build-pdf.sh build-pdf.sh
# Auto-detect single .md file in directory (landscape default)
./build-pdf.sh
# Portrait mode
./build-pdf.sh --portrait document.md
# Monospace font for ASCII diagrams
./build-pdf.sh --monospace diagrams.md
# Explicit input/output
./build-pdf.sh input.md output.pdf
DETECT_EOF
Options:
Flag
Description
--landscape
Landscape orientation (default)
--portrait
Portrait orientation
--monospace
Use DejaVu Sans Mono - ideal for ASCII diagrams
--hide-details
Hide <details> blocks (e.g., graph-easy source) from PDF
-h, --help
Show help message
Features:
- ✅ Auto-detects input file (if single .md exists)
- ✅ Auto-detects bibliography (
references.bib) and CSL files
- ✅ Always uses production-proven LaTeX preamble from skill
- ✅ Pre-flight checks (pandoc, xelatex, files exist)
- ✅ Post-build validation (file size, page count)
- ✅ Code blocks stay on same page (no splitting across pages)
- ✅ Lua filter to hide
<details>blocks from PDF output
Landscape PDF (Quick Command)
For landscape PDFs with blue hyperlinks (no build-pdf.sh dependency):
pandoc file.md -o file.pdf \
--pdf-engine=xelatex \
-V geometry:a4paper,landscape \
-V geometry:margin=1in \
-V fontsize=11pt \
-V mainfont="DejaVu Sans" \
-V colorlinks=true \
-V linkcolor=blue \
-V urlcolor=blue \
--toc --toc-depth=2 \
--number-sections
Use landscape for: Wide data tables, comparison matrices, technical docs with code blocks.
Manual Command (With LaTeX Preamble)
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
pandoc document.md \
-o document.pdf \
--pdf-engine=xelatex \
--toc \
--toc-depth=3 \
--number-sections \
-V geometry:margin=1in \
-V mainfont="DejaVu Sans" \
-H ${CLAUDE_PLUGIN_ROOT}/skills/pandoc-pdf-generation/assets/table-spacing-template.tex
SKILL_SCRIPT_EOF
ASCII Diagrams: Always Use graph-easy
CRITICAL: Never manually type ASCII diagrams. Always use the itp:graph-easy skill.
Manual ASCII art causes alignment issues in PDFs. The graph-easy skill ensures:
- Proper boxart character alignment
- Consistent spacing
- Reproducible output
# Invoke the skill for general diagrams
Skill(itp:graph-easy)
# For ADR architecture diagrams
Skill(itp:adr-graph-easy-architect)
Also important: Keep annotations OUTSIDE code blocks. Don't add inline comments like # contains: file1, file2 inside diagram code blocks - they break alignment.
Hiding Content for PDF Output
Use --hide-details to remove <details> blocks from PDF output. This is useful when:
- graph-easy source blocks: Keep source in markdown for diagram regeneration, but hide from printed PDFs
- Technical implementation notes: Show in web/markdown view, hide from printed handouts
- Collapsible sections: HTML
<details>tags don't render as collapsible in PDF
Usage:
./build-pdf.sh --hide-details document.md
Markdown pattern:
## My Section
┌─────┐ ┌─────┐
│ Box │ ──> │ Box │
└─────┘ └─────┘
[Box] -> [Box]
With --hide-details, the entire <details> block is stripped from PDF output while remaining visible in markdown/HTML.
Verification Checklist
Before considering a PDF "done", verify:
Pre-Generation:
- No manual section numbering in markdown (use
--number-sections)
- All ASCII diagrams generated via
itp:graph-easyskill
- Annotations are outside code blocks, not inside
Post-Generation:
- Open PDF and visually inspect each page
- Verify diagrams don't break across pages
- Check section numbering is correct (no "1. 1. Title" duplication)
- Confirm bullet lists render as bullets, not inline dashes
Pre-Print:
- Get user approval before printing
- Confirm orientation preference (landscape/portrait)
- Confirm duplex preference (one-sided/two-sided)
Printing Workflow
Always let the user review the PDF before printing.
Open for review:
open output.pdf
Print one-sided (simplex):
lpr -P "PRINTER_NAME" -o Duplex=None output.pdf
Print two-sided (duplex):
lpr -P "PRINTER_NAME" -o Duplex=DuplexNoTumble output.pdf # Long-edge binding
lpr -P "PRINTER_NAME" -o Duplex=DuplexTumble output.pdf # Short-edge binding
Find printer name:
lpstat -p -d
Never print without user approval - this wastes paper if issues exist.
Reference Documentation
For detailed information, see:
- Core Development Principles - START HERE - Universal principles learned from production failures
- Markdown for PDF - Markdown structure patterns for clean landscape PDFs
- YAML Front Matter Structure - YAML metadata patterns
- LaTeX Customization - Preamble and table formatting
- Bibliography &#x26; Citations - BibTeX and CSL styles
- Document Patterns - Document type templates
- Troubleshooting - Common issues and fixes
Troubleshooting
Issue
Cause
Solution
Font not found
DejaVu Sans not installed
brew install font-dejavu
xelatex not found
MacTeX not installed
brew install --cask mactex
Table breaks across pages
Missing longtable package
Include table-spacing-template.tex preamble
Double section numbers
Manual numbering in markdown
Remove manual numbers, use --number-sections only
ASCII diagram misaligned
Manual ASCII art
Use graph-easy skill for all diagrams
Bullet list renders as dashes
Markdown formatting issue
Check for proper blank lines before lists
Bibliography not rendering
Missing references.bib
Create .bib file or remove --bibliography flag
PDF file size too large
Embedded fonts
Use --pdf-engine-opt=-dEmbedAllFonts=false
Post-Execution Reflection
After this skill completes, check before closing:
- Did the command succeed? — If not, fix the instruction or error table that caused the failure.
- Did parameters or output change? — If the underlying tool's interface drifted, update Usage examples and Parameters table to match.
- Was a workaround needed? — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.
Only update if the issue is real and reproducible — not speculative.