Resilient multi-format document generation with environment checks, auto-sanitization, and fallback engines
51
56%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./benchmarks/gdpval/skills/document-gen-fallback-enhanced-enhanced-618c9b/SKILL.mdUse this skill when generating documents in multiple formats (.docx, .pdf, .html) and you need:
Trigger this workflow when:
shell_agent returns unknown/unclear errors on document generationBefore starting, verify your environment has the required tools:
run_shell
command: which pandoc && pandoc --version | head -1run_shell
command: which pdflatex || which xelatex || which wkhtmltopdf || echo "No PDF engine found"run_shell
command: python3 -c "import fpdf; print('fpdf2 available')" 2>/dev/null || echo "fpdf2 not available"run_shell
command: python3 -c "import reportlab; print('reportlab available')" 2>/dev/null || echo "reportlab not available"If pandoc is missing: Install via apt-get install pandoc or brew install pandoc
If no PDF engine found: Choose fallback approach:
apt-get install texlive-latex-recommended texlive-fonts-recommendedapt-get install wkhtmltopdfSplit the workflow into discrete, observable steps with automatic format detection:
write_file to create source Markdown| Format | Unicode Support | Sanitization Needed | Recommended Engine |
|---|---|---|---|
.docx | Excellent | No | pandoc (default) |
.html | Excellent | No | pandoc (default) |
.pdf | Limited (LaTeX) | Yes | xelatex > pdflatex > wkhtmltopdf > fpdf2 |
.pptx | Good | No | pandoc (if available) or python-pptx |
| Character | Issue | Safe Replacement |
|---|---|---|
— (em dash) | May not render | -- or - |
– (en dash) | May not render | - |
" " (curly quotes) | Encoding errors | " " (straight quotes) |
' ' (curly apostrophe) | Encoding errors | ' (straight apostrophe) |
… (ellipsis) | May not render | ... |
→ ← ↑ ↓ (arrows) | LaTeX incompatibility | -> <- ^ v |
✓ ✗ (checkmarks) | May not render | [x] [ ] |
★ ● (symbols) | May not render | * - |
© ® ™ | May require packages | (c) (r) (tm) |
| Non-ASCII letters (é, ñ, ü) | Font-dependent | Use xeLaTeX or replace |
Verify environment before proceeding:
run_shell
command: pandoc --version >/dev/null 2>&1 && echo "PANDOC_OK" || echo "PANDOC_MISSING"If PANDOC_MISSING: Either install pandoc or use Alternative PDF Generation (Python-based)
Write your document content as Markdown to a source file:
write_file
path: /tmp/document_source.md
content: |
# Document Title
## Section 1
Content with original unicode characters...
## Section 2
More content...Only sanitize if generating PDF. Create sanitized version for PDF conversion:
write_file
path: /tmp/document_source_sanitized.md
content: |
# Document Title
## Section 1
Content with unicode replaced (em-dash -> --, curly quotes -> straight, etc.)
## Section 2
More content...Optional: Use sanitization script (see Unicode Sanitization Script section below):
run_shell
command: ./sanitize_for_pdf.sh /tmp/document_source.md /tmp/document_source_sanitized.mdNote: Keep the original unsanitized file for DOCX/HTML conversion (these formats handle Unicode better).
Use appropriate commands for each format. Use sanitized source for PDF, original for others.
DOCX (from original):
run_shell
command: pandoc /tmp/document_source.md -o output.docxPDF (from sanitized, with engine priority):
run_shell
command: pandoc /tmp/document_source_sanitized.md -o output.pdf --pdf-engine=xelatexIf xelatex fails, try pdflatex:
run_shell
command: pandoc /tmp/document_source_sanitized.md -o output.pdf --pdf-engine=pdflatexIf LaTeX engines fail, try wkhtmltopdf:
run_shell
command: pandoc /tmp/document_source_sanitized.md -o output.pdf --pdf-engine=wkhtmltopdfHTML (from original):
run_shell
command: pandoc /tmp/document_source.md -o output.htmlCheck that files were created and have content:
run_shell
command: ls -lh output.* && file output.*run_shell
command: test -s output.pdf && echo "PDF has content" || echo "PDF is empty"Is pandoc available?
├─ NO → Use Python fallback (fpdf2 or reportlab)
└─ YES → Is LaTeX available?
├─ YES (xelatex) → Use: pandoc --pdf-engine=xelatex (best Unicode)
├─ YES (pdflatex) → Use: pandoc --pdf-engine=pdflatex + sanitization
├─ YES (wkhtmltopdf) → Use: pandoc --pdf-engine=wkhtmltopdf
└─ NO → Install LaTeX or use Python fallbackWhen pandoc or LaTeX is unavailable, use Python libraries directly:
run_shell
command: python3 << 'EOF'
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
# Note: fpdf2 has limited Unicode support - use Latin-1 or embed fonts
pdf.cell(200, 10, txt="Document Title", ln=True, align='C')
pdf.output("output.pdf")
EOFrun_shell
command: python3 << 'EOF'
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# Register a Unicode font if needed
# pdfmetrics.registerFont(TTFont('UnicodeFont', 'path/to/font.ttf'))
c = canvas.Canvas("output.pdf", pagesize=letter)
c.drawString(100, 750, "Document Title")
c.save()
EOFrun_shell
command: python3 << 'EOF'
import markdown
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
# Read markdown
with open('/tmp/document_source.md', 'r', encoding='utf-8') as f:
md_content = f.read()
# Convert to HTML
html_content = markdown.markdown(md_content)
# Create PDF
doc = SimpleDocTemplate("output.pdf", pagesize=letter)
styles = getSampleStyleSheet()
story = []
# Parse HTML and add to story (simplified - use html2text for production)
story.append(Paragraph("Document Content", styles['Normal']))
doc.build(story)
print("PDF created successfully")
EOF# Generate Multi-Format Report
## Step 0: Check environment
run_shell
command: pandoc --version >/dev/null 2>&1 && echo "PANDOC_OK" || echo "PANDOC_MISSING"
## Step 1: Write Markdown source
write_file
path: /tmp/report.md
content: |
# Quarterly Report
## Executive Summary
Performance metrics and analysis...
## Key Findings
— Major finding with em-dash
"Quote" with curly quotes
✓ Completed items
## Step 2: Create sanitized version (for PDF only)
write_file
path: /tmp/report_sanitized.md
content: |
# Quarterly Report
## Executive Summary
Performance metrics and analysis...
## Key Findings
-- Major finding with em-dash
"Quote" with straight quotes
[x] Completed items
## Step 3: Convert to DOCX (from original)
run_shell
command: pandoc /tmp/report.md -o report.docx
## Step 4: Convert to PDF (from sanitized, with xelatex)
run_shell
command: pandoc /tmp/report_sanitized.md -o report.pdf --pdf-engine=xelatex
## Step 5: Convert to HTML (from original)
run_shell
command: pandoc /tmp/report.md -o report.html
## Step 6: Verify all outputs
run_shell
command: ls -lh report.* && echo "All files created"| Error | Likely Cause | Recovery Action |
|---|---|---|
pandoc: command not found | Pandoc not installed | Install pandoc or use Python fallback |
pdflatex not found | LaTeX missing | Use --pdf-engine=xelatex or wkhtmltopdf |
! LaTeX Error: File X.sty not found | Missing LaTeX package | Install package or use xelatex/wkhtmltopdf |
Encoding error | Unicode in PDF | Use sanitized file + xelatex engine |
wkhtmltopdf: command not found | wkhtmltopdf missing | Install or use xelatex/pdflatex |
PDF is empty (0 bytes) | Conversion silently failed | Check pandoc stderr, try alternative engine |
fpdf2 Unicode error | Non-Latin characters | Use reportlab with Unicode font or sanitize |
Save as sanitize_for_pdf.sh:
#!/bin/bash
# sanitize_for_pdf.sh - Replace problematic unicode chars for LaTeX/PDF
if [ -z "$1" ]; then
echo "Usage: $0 <input.md> [output.md]"
exit 1
fi
INPUT="$1"
OUTPUT="${2:-${1%.md}_sanitized.md}"
sed -e 's/—/--/g' \
-e 's/–/-/g' \
-e 's/"([^"]*)"/"\1"/g' \
-e "s/'([^']*)/'\1'/g" \
-e 's/…/.../g' \
-e 's/→/->/g' \
-e 's/←/<-/g' \
-e 's/✓/[x]/g' \
-e 's/✗/[ ]/g' \
-e 's/©/(c)/g' \
-e 's/®/(r)/g' \
-e 's/™/(tm)/g' \
"$INPUT" > "$OUTPUT"
echo "Sanitized: $INPUT -> $OUTPUT"Make executable: chmod +x sanitize_for_pdf.sh
Usage:
run_shell
command: ./sanitize_for_pdf.sh /tmp/document_source.md /tmp/document_source_sanitized.md# Markdown to Word
pandoc input.md -o output.docx
# Markdown to PDF (LaTeX - default pdflatex)
pandoc input.md -o output.pdf
# Markdown to PDF with xelatex (best Unicode support)
pandoc input.md -o output.pdf --pdf-engine=xelatex
# Markdown to PDF with wkhtmltopdf (HTML-based, no LaTeX)
pandoc input.md -o output.pdf --pdf-engine=wkhtmltopdf
# Markdown to HTML
pandoc input.md -o output.html
# With metadata
pandoc input.md -o output.pdf --metadata title="Document Title"
# With custom reference doc (DOCX)
pandoc input.md -o output.docx --reference-doc=template.docx
# With custom template (HTML/PDF)
pandoc input.md --template=template.html -o output.html
# Force UTF-8 input
pandoc -f markdown+utf8 input.md -o output.pdfPDF generation fails with encoding error:
--pdf-engine=xelatex for better Unicode support-f markdown+utf8 to pandoc commandPDF generation fails: LaTeX not found:
apt-get install texlive-latex-recommended texlive-fonts-recommended--pdf-engine=wkhtmltopdfDOCX formatting issues:
--reference-doc=template.docx for custom stylesUnicode/encoding errors in any format:
file -i source.md-f markdown+utf8 to pandoc commandSpecial characters not rendering in PDF:
Missing pandoc:
apt-get install pandocbrew install pandoc| Scenario | Recommended Approach |
|---|---|
| Simple DOCX/HTML, no Unicode | shell_agent is fine |
| PDF generation required | Manual workflow (this skill) |
| Multiple formats from one source | Manual workflow (this skill) |
| Heavy Unicode/special characters | Manual workflow with sanitization |
shell_agent failed with unknown error | Manual workflow (this skill) |
| Need explicit error visibility | Manual workflow (this skill) |
| Environment constraints (no pandoc) | Python fallback (this skill) |
After successful manual workflow: You can attempt shell_agent for similar future tasks, but keep this workflow as your known-working fallback.
document-gen-fallback: Original fallback workflow (less Unicode guidance)write-file-fallback-report: For when multiple tools fail simultaneouslyspreadsheet-direct-python: For Excel/CSV generation with PythonExpected success rate: 85%+ with proper environment setup Fallback activation: Use Python fallback if pandoc/LaTeX unavailable Verification: Always verify output files exist AND have content (>0 bytes) *** End Files *** Begin Files
c5a9c4b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.