# markdown-to-pdf
> Convert templated markdown to branded PDFs. Create documents from 12 templates (scientific, project-mgmt, technical), generate professional PDFs with Oligon styling.
- Author: pickleton89
- Repository: pickleton89/claude-scientific-writer_fork
- Version: 20251230223523
- Stars: 0
- Forks: 0
- Last Updated: 2026-02-06
- Source: https://github.com/pickleton89/claude-scientific-writer_fork
- Web: https://mule.run/skillshub/@@pickleton89/claude-scientific-writer_fork~markdown-to-pdf:20251230223523
---
---
name: markdown-to-pdf
version: 1.0.0
description: "Convert templated markdown to branded PDFs. Create documents from 12 templates (scientific, project-mgmt, technical), generate professional PDFs with Oligon styling."
allowed-tools: [Read, Write, Edit, Bash]
---
# Markdown to PDF - Branded Document Conversion
This skill bridges the template infrastructure and PDF component system to provide a complete markdown-to-PDF workflow. It uses `TemplateParser` for document parsing and `oligon_reports` components for branded PDF generation.
**Dependencies:**
- `oligon_reports.templates.TemplateParser` - Template parsing and validation
- `oligon_reports.components` - PDF visual components
- `oligon_reports.ReportGenerator` - PDF orchestration
## Prerequisites
Before using this skill, verify the oligon_reports package is installed:
```bash
uv sync # Install all project dependencies
```
**Quick verification:**
```python
from oligon_reports import ReportGenerator
from oligon_reports.templates import TemplateParser
print("Dependencies ready")
```
If imports fail, ensure you're in the project directory with `pyproject.toml`.
## Trigger Conditions
Use this skill when:
- Listing available document templates
- Creating new documents from templates
- Converting templated markdown to branded PDFs
- Generating professional reports with Oligon styling
Do NOT use this skill when:
- Converting arbitrary files to markdown → use `markitdown`
- Creating LaTeX/academic papers → use `scientific-writing`
- Making PowerPoint presentations → use `scientific-slides` or `pptx-posters`
- Working with existing PDFs (extraction, forms) → use `document-skills/pdf`
## Command Selection
```
What does the user need?
│
├─ See available templates?
│ └─ YES → /list-templates
│ Returns table of 12 document types with categories
│
├─ Start a new document from template?
│ └─ YES → /new-doc
│ Creates _YYYYMMDD.md in current directory
│
└─ Convert existing markdown to PDF?
└─ YES → /doc-to-pdf
│
├─ Parses and validates document
├─ Shows structure for confirmation
├─ Maps elements to PDF components
└─ Generates branded PDF in output/
```
## Template Categories
| Category | Templates | Use Case |
|----------|-----------|----------|
| scientific | analysis-report, literature-review, data-report | Research outputs |
| project-mgmt | meeting-notes, project-status, phase-plan, task-list | Project tracking |
| technical | technical-spec, method-guide, standards-guide | Documentation |
| meta | agent-definition, readme | System docs |
## Commands
### /list-templates
**Purpose:** Display all available document templates
**Workflow:**
1. Call `TemplateParser.list_templates()`
2. Format as markdown table
3. Display with type, category, and description
**Output Example:**
```
| Type | Category | Description |
|-------------------|-----------------|---------------------------------------|
| analysis-report | scientific | Structured analysis with findings |
| literature-review | scientific | Systematic literature review |
| data-report | scientific | Data analysis and visualization |
| meeting-notes | project-mgmt | Meeting documentation |
| project-status | project-mgmt | Project status update |
| phase-plan | project-mgmt | Implementation phase planning |
| task-list | project-mgmt | Task tracking document |
| technical-spec | technical | Technical specification |
| method-guide | technical | Methodology documentation |
| standards-guide | technical | Standards and guidelines |
| agent-definition | meta | AI agent behavior definition |
| readme | meta | Project documentation |
```
**Implementation:**
```python
from oligon_reports.templates import TemplateParser
templates = TemplateParser.list_templates()
# Returns: [{"type": "...", "category": "...", "description": "..."}, ...]
```
---
### /new-doc \
**Purpose:** Create a new document from a template
**Arguments:**
- `type` (required): Document type from template list
**Workflow:**
1. Validate `` exists in template list
2. Get template content: `TemplateParser.get_template(type)`
3. Generate filename: `_YYYYMMDD.md`
4. Write to current directory
5. Report success
**Output Example:**
```
Created: analysis-report_20251228.md
Template type: analysis-report (scientific)
Next: Edit the document, then run /doc-to-pdf analysis-report_20251228.md
```
**Implementation:**
```python
from datetime import date
from oligon_reports.templates import TemplateParser
template_content = TemplateParser.get_template("analysis-report")
filename = f"analysis-report_{date.today().strftime('%Y%m%d')}.md"
with open(filename, "w") as f:
f.write(template_content)
```
**Error Handling:**
- If type not found → Show available types with `/list-templates`
- If file exists → Prompt to overwrite or use incremental name
---
### /doc-to-pdf \ [--figures]
**Purpose:** Convert a templated markdown document to branded PDF
**Arguments:**
- `file` (required): Path to markdown file
- `--figures` (optional): Generate figures using `scientific-schematics`
**Workflow:**
#### Step 1: Parse & Detect
```python
from oligon_reports.templates import TemplateParser
parser = TemplateParser()
tree = parser.parse(content)
doc_type = tree.frontmatter.type # e.g., "analysis-report"
```
#### Step 2: Show Structure for Confirmation
Present document structure and detected elements for user approval:
```
📄 Document: analysis-report_20251228.md
📋 Type: analysis-report (detected from frontmatter)
Structure:
├── 1. Objective
├── 2. Key Questions
├── 3. Methodology
│ └── 3.1 Data Sources
├── 4. Findings
│ ├── Finding 1: [title]
│ ├── Finding 2: [title]
│ └── Finding 3: [title]
└── 5. Recommendations
Elements Detected:
- 3 tables (→ StatusTable/GradedTable/BaseTable)
- 3 finding cards (→ FindingCard)
- 2 code blocks (→ MethodBlock)
- 1 callout (→ CalloutBox)
⚠️ Validation:
- ✅ All required sections present
- ⚠️ Missing optional: executive_summary
Proceed with PDF generation? [Y/n/edit]
```
#### Step 3: Map Elements to Components
Use the component mapping (see `{baseDir}/references/component_map.md`):
| Markdown Element | Detection | PDF Component |
|------------------|-----------|---------------|
| Tables with ✓/✗ | Status symbols in cells | `StatusTable` |
| Tables with grades | A-F or tier values | `GradedTable` |
| Regular tables | Standard markdown | Standard table |
| `#### Finding N:` | Heading pattern | `FindingCard` |
| Code blocks | Triple backticks | `MethodBlock` |
| `> **Type:**` | Blockquote + bold | `CalloutBox` |
| Checklists | `- [ ]` pattern | Standard list |
#### Step 4: Generate PDF
```python
from oligon_reports import ReportGenerator
generator = ReportGenerator(output_dir="output")
generator.add_title(tree.frontmatter.title)
for section in tree.sections:
generator.add_section(section.title, section.content)
for element in section.elements:
# Map to appropriate component
component = map_element_to_component(element)
generator.add_component(component)
pdf_path = generator.build(f"{filename_stem}.pdf")
```
**Output:**
- Creates `output/` directory if needed
- Generates `output/.pdf`
- Adds `output/` to `.gitignore` if not present
#### Step 5: Optional Figure Enhancement
If `--figures` flag provided:
```
Generating figures for document...
[Invokes scientific-schematics for each figure placeholder]
```
**Success Output:**
```
✅ PDF generated: output/analysis-report_20251228.pdf
Summary:
- 5 sections rendered
- 3 FindingCards
- 2 StatusTables
- 1 MethodBlock
- Brand styling applied (Oligon)
```
**Error Handling:**
| Error | Cause | Solution |
|-------|-------|----------|
| `FileNotFoundError` | Markdown file doesn't exist | Verify path, check working directory |
| `KeyError: 'type'` | Missing frontmatter type field | Add `type: ` to YAML header |
| `ValidationError` | Required sections missing | Check template schema for required fields |
| `PermissionError` on output/ | Directory not writable | Check permissions or use different output path |
| `ModuleNotFoundError` | oligon_reports not installed | Run `uv sync` in project directory |
**Recovery workflow:**
```
Error detected?
├─ Missing frontmatter → Add YAML header with type, title, date
├─ Validation errors → Compare against template schema
├─ Import errors → Run `uv sync` and retry
└─ Permission errors → Check output/ directory permissions
```
## Component Mapping Reference
See `{baseDir}/references/component_map.md` for the complete element-to-component mapping.
### Quick Reference
| Pattern | Component | Example |
|---------|-----------|---------|
| `✓`, `✗`, `✔`, `✘` in table | StatusTable | Compliance matrix |
| `A`, `B`, `C`, `D`, `F` in table | GradedTable | Rating table |
| `#### Finding [0-9]:` | FindingCard | Key findings |
| Triple backticks | MethodBlock | Code/methods |
| `> **Note:**` | CalloutBox (info) | Information |
| `> **Warning:**` | CalloutBox (warning) | Caution |
| `> **Important:**` | CalloutBox (alert) | Critical |
| `- [ ]` or `- [x]` | Checklist | Tasks |
## Complete Workflow Example
### Creating a New Analysis Report
```
> /list-templates
| Type | Category | Description |
|-------------------|-----------------|---------------------------------------|
| analysis-report | scientific | Structured analysis with findings |
...
> /new-doc analysis-report
Created: analysis-report_20251228.md
Template type: analysis-report (scientific)
[User edits the document with their content]
> /doc-to-pdf analysis-report_20251228.md
📄 Document: analysis-report_20251228.md
📋 Type: analysis-report
Structure:
├── 1. Objective
├── 2. Methodology
├── 3. Findings
└── 4. Recommendations
Elements Detected:
- 2 tables (→ StatusTable)
- 3 finding cards (→ FindingCard)
Proceed with PDF generation? [Y/n/edit]
> Y
✅ PDF generated: output/analysis-report_20251228.pdf
```
## Success Criteria
**Command: /list-templates**
- [ ] Shows all 12 template types
- [ ] Grouped by category
- [ ] Descriptions are helpful
**Command: /new-doc**
- [ ] Creates valid markdown file
- [ ] Filename includes date
- [ ] Template content is complete
**Command: /doc-to-pdf**
- [ ] Parses document without errors
- [ ] Shows accurate structure tree
- [ ] Correctly detects element types
- [ ] PDF matches brand styling
- [ ] Output folder is gitignored
## Common Pitfalls
### 1. Missing Frontmatter
**Anti-pattern:**
Converting a markdown file without YAML frontmatter
**Solution:**
```markdown
---
type: analysis-report
title: My Analysis
date: 2025-12-28
author: Jane Doe
---
# My Analysis
...
```
---
### 2. Wrong Element Detection
**Anti-pattern:**
Regular table detected as StatusTable
**Solution:**
StatusTable detection requires actual status symbols (✓, ✗, ✔, ✘) in cells, not just checkmark text.
---
### 3. Missing Dependencies
**Anti-pattern:**
```python
from oligon_reports import ReportGenerator
# ModuleNotFoundError
```
**Solution:**
```bash
uv sync # Ensure oligon_reports is installed
```
---
### 4. Output Directory Issues
**Anti-pattern:**
PDF generation fails because output/ doesn't exist
**Solution:**
The skill automatically creates `output/` and adds it to `.gitignore`.
## Related Skills
| Skill | Relationship |
|-------|-------------|
| `oligon-brand` | Brand colors and tokens—`oligon_reports` uses these for PDF styling |
| `markitdown` | Convert documents TO markdown (reverse direction) |
| `document-skills/pdf` | Low-level PDF manipulation (forms, extraction) |
| `scientific-writing` | Create academic manuscripts (different output format) |
| `scientific-schematics` | Generate figures for `--figures` integration |
| `venue-templates` | Journal-specific formatting (use before /doc-to-pdf) |
**Skill Selection:**
See `SKILL_ROUTER.md` for decision trees when multiple skills may apply.
## Reference Documents
| Document | Purpose |
|----------|---------|
| `{baseDir}/references/component_map.md` | Complete element → component mapping |
| `src/oligon_reports/templates/` | Template schemas and markdown files |
| `src/oligon_reports/components.py` | PDF component implementations |
| `../oligon-brand/references/brand-colors-full.md` | Brand colors and visual identity (V4) |
| `../oligon-brand/tokens/brand-tokens.json` | Machine-readable brand tokens |
## API Reference
```python
from oligon_reports.templates import TemplateParser
# List available templates
templates = TemplateParser.list_templates()
# → [{"type": "...", "category": "...", "description": "..."}, ...]
# Get template content
content = TemplateParser.get_template("analysis-report")
# → Markdown string
# Parse document
parser = TemplateParser()
tree = parser.parse(markdown_content)
# → DocumentTree with frontmatter, sections, elements
# Validate
errors = parser.validate(tree)
# → List of ValidationError
```