File size: 2,769 Bytes
b2b6341 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse
from pydantic import BaseModel
from fpdf import FPDF
import os
import tempfile
import uuid
router = APIRouter()
class ExportRequest(BaseModel):
title: str
content: str
citations: list[dict] = []
class PDFGenerator(FPDF):
def header(self):
self.set_font('helvetica', 'B', 12)
self.cell(0, 10, 'InteleX Research Memorandum', 0, 1, 'C')
self.ln(5)
def footer(self):
self.set_y(-15)
self.set_font('helvetica', 'I', 8)
self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C')
import re
def _clean_text(text: str) -> str:
"""Strip emojis and non-latin characters that crash FPDF."""
if not text:
return " "
# Remove markdown headers
text = text.replace('#', '').replace('*', '')
# Keep only common latin characters and punctuation for standard fonts
cleaned = re.sub(r'[^\x00-\x7F]+', '', text)
return cleaned if cleaned.strip() else "[Non-supported characters]"
@router.post("/pdf")
async def export_pdf(req: ExportRequest):
try:
pdf = PDFGenerator()
pdf.add_page()
# Ensure we are at the left margin to avoid "horizontal space" errors
pdf.set_x(pdf.l_margin)
# Title
pdf.set_font("helvetica", 'B', 16)
title = _clean_text(req.title)
pdf.multi_cell(0, 10, title)
pdf.ln(10)
# Content
pdf.set_font("helvetica", '', 11)
content = _clean_text(req.content)
pdf.set_x(pdf.l_margin) # Reset X before body
pdf.multi_cell(0, 7, content)
# Citations
if req.citations:
pdf.ln(10)
pdf.set_font("helvetica", 'B', 12)
pdf.set_x(pdf.l_margin)
pdf.cell(0, 10, 'Sources & Citations', 0, 1)
pdf.set_font("helvetica", '', 9)
for i, cite in enumerate(req.citations):
source_title = cite.get('source_title') or cite.get('sourceTitle') or "Source"
ref = cite.get('reference') or ""
text = f"[{i+1}] {source_title} - {ref}"
pdf.set_x(pdf.l_margin)
pdf.multi_cell(0, 5, _clean_text(text))
# Save to temp file
tmp_dir = tempfile.gettempdir()
filename = f"research_{uuid.uuid4().hex[:8]}.pdf"
filepath = os.path.join(tmp_dir, filename)
pdf.output(filepath)
return FileResponse(
path=filepath,
filename=filename,
media_type='application/pdf'
)
except Exception as e:
print(f"[Export] PDF Error: {e}")
raise HTTPException(status_code=500, detail=str(e))
|