127 lines
4.0 KiB
Python
127 lines
4.0 KiB
Python
from reportlab.lib import colors
|
||
from reportlab.lib.pagesizes import A4
|
||
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
|
||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
||
from reportlab.pdfbase import pdfmetrics
|
||
from reportlab.pdfbase.ttfonts import TTFont
|
||
from io import BytesIO
|
||
import re
|
||
|
||
|
||
class Exporter:
|
||
def __init__(self):
|
||
self.styles = getSampleStyleSheet()
|
||
self.setup_styles()
|
||
|
||
def _register_fonts(self):
|
||
pdfmetrics.registerFont(TTFont("Helvetica", "Helvetica"))
|
||
pdfmetrics.registerFont(TTFont("Helvetica-Bold", "Helvetica-Bold"))
|
||
|
||
def setup_styles(self):
|
||
self.styles.add(
|
||
ParagraphStyle(
|
||
name="Header",
|
||
fontSize=14,
|
||
textColor=colors.HexColor("#10B981"),
|
||
spaceAfter=12,
|
||
fontName="Helvetica-Bold",
|
||
encoding="utf-8",
|
||
)
|
||
)
|
||
|
||
self.styles.add(
|
||
ParagraphStyle(
|
||
name="Content",
|
||
fontSize=11,
|
||
textColor=colors.black,
|
||
spaceAfter=8,
|
||
fontName="Helvetica",
|
||
encoding="utf-8",
|
||
)
|
||
)
|
||
|
||
self.styles.add(
|
||
ParagraphStyle(
|
||
name="Bullet-Point",
|
||
fontSize=11,
|
||
leftIndent=20,
|
||
bulletIndent=10,
|
||
spaceAfter=5,
|
||
fontName="Helvetica",
|
||
encoding="utf-8",
|
||
)
|
||
)
|
||
|
||
def clean_text(self, text: str) -> str:
|
||
if not isinstance(text, str):
|
||
text = text.decode("utf-8")
|
||
|
||
text = text.replace("ı", "i").replace("İ", "I")
|
||
text = text.replace("ğ", "g").replace("Ğ", "G")
|
||
text = text.replace("ü", "u").replace("Ü", "U")
|
||
text = text.replace("ş", "s").replace("Ş", "S")
|
||
text = text.replace("ö", "o").replace("Ö", "O")
|
||
text = text.replace("ç", "c").replace("Ç", "C")
|
||
|
||
text = re.sub(
|
||
r"\[header\](.*?)\[/header\]", r'<para style="Header">\1</para>', text
|
||
)
|
||
text = re.sub(r"\[bold\](.*?)\[/bold\]", r"<b>\1</b>", text)
|
||
return text
|
||
|
||
def create_watermark(self, canvas, doc):
|
||
canvas.saveState()
|
||
canvas.setFillColor(colors.HexColor("#10B981"))
|
||
canvas.setFont("Helvetica", 8)
|
||
canvas.drawString(30, 20, "Generated by docklink.io")
|
||
canvas.restoreState()
|
||
|
||
def export_pdf(self, data: str) -> BytesIO:
|
||
buffer = BytesIO()
|
||
content = []
|
||
cleaned_text = self.clean_text(data)
|
||
|
||
doc = SimpleDocTemplate(
|
||
buffer,
|
||
pagesize=A4,
|
||
rightMargin=30,
|
||
leftMargin=30,
|
||
topMargin=30,
|
||
bottomMargin=30,
|
||
)
|
||
|
||
lines = cleaned_text.split("\n")
|
||
|
||
for line in lines:
|
||
if line.strip():
|
||
if (
|
||
line.startswith("<h1>")
|
||
or line.startswith('<para style="Header">')
|
||
or "header" in line
|
||
):
|
||
# Header section
|
||
text = line.replace("<h1>", "").replace("</h1>", "")
|
||
content.append(Paragraph(text, self.styles["Header"]))
|
||
elif line.startswith("-"):
|
||
# Bullet point
|
||
text = line.strip()
|
||
content.append(Paragraph(f"- {text}", self.styles["Bullet-Point"]))
|
||
else:
|
||
# Normal text
|
||
content.append(Paragraph(line, self.styles["Content"]))
|
||
|
||
content.append(Spacer(1, 2))
|
||
|
||
try:
|
||
doc.build(
|
||
content,
|
||
onFirstPage=self.create_watermark,
|
||
onLaterPages=self.create_watermark,
|
||
)
|
||
buffer.seek(0)
|
||
return buffer
|
||
except Exception as e:
|
||
raise ValueError(
|
||
f"Error: {e} Content too large or complex to export to PDF"
|
||
)
|