mirror of
https://github.com/velocitatem/cvfs.git
synced 2026-05-31 16:53:38 +00:00
Agent-Logs-Url: https://github.com/velocitatem/cvfs/sessions/fb35fb9a-a89e-4df0-9584-109f7151509c Co-authored-by: velocitatem <60182044+velocitatem@users.noreply.github.com>
80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from io import BytesIO
|
|
|
|
from docx import Document
|
|
from reportlab.lib import colors
|
|
from reportlab.lib.enums import TA_CENTER, TA_LEFT
|
|
from reportlab.lib.pagesizes import A4
|
|
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
|
|
from reportlab.lib.units import cm
|
|
from reportlab.platypus import HRFlowable, Paragraph, SimpleDocTemplate, Spacer
|
|
|
|
from .parser import _detect_block_type
|
|
|
|
_STYLES = getSampleStyleSheet()
|
|
|
|
_STYLE_MAP: dict[str, ParagraphStyle] = {
|
|
"heading": ParagraphStyle(
|
|
"CVHeading", parent=_STYLES["Normal"],
|
|
fontSize=15, leading=20, spaceBefore=10, spaceAfter=4,
|
|
textColor=colors.HexColor("#111111"), fontName="Helvetica-Bold",
|
|
),
|
|
"meta": ParagraphStyle(
|
|
"CVMeta", parent=_STYLES["Normal"],
|
|
fontSize=9, leading=13, spaceAfter=2, textColor=colors.HexColor("#555555"),
|
|
),
|
|
"summary": ParagraphStyle(
|
|
"CVSummary", parent=_STYLES["Normal"],
|
|
fontSize=10, leading=14, spaceAfter=6, textColor=colors.HexColor("#333333"),
|
|
),
|
|
"bullet": ParagraphStyle(
|
|
"CVBullet", parent=_STYLES["Normal"],
|
|
fontSize=10, leading=14, spaceAfter=3, leftIndent=14,
|
|
bulletIndent=0, textColor=colors.HexColor("#222222"),
|
|
),
|
|
"skills": ParagraphStyle(
|
|
"CVSkills", parent=_STYLES["Normal"],
|
|
fontSize=10, leading=14, spaceAfter=3, textColor=colors.HexColor("#222222"),
|
|
),
|
|
"text": ParagraphStyle(
|
|
"CVText", parent=_STYLES["Normal"],
|
|
fontSize=10, leading=14, spaceAfter=4, textColor=colors.HexColor("#222222"),
|
|
),
|
|
}
|
|
|
|
|
|
def docx_bytes_to_pdf(docx_bytes: bytes) -> bytes:
|
|
doc = Document(BytesIO(docx_bytes))
|
|
buf = BytesIO()
|
|
pdf = SimpleDocTemplate(
|
|
buf, pagesize=A4,
|
|
leftMargin=2.2 * cm, rightMargin=2.2 * cm,
|
|
topMargin=2 * cm, bottomMargin=2 * cm,
|
|
)
|
|
story: list = []
|
|
prev_type: str | None = None
|
|
|
|
for para in doc.paragraphs:
|
|
text = para.text.strip()
|
|
if not text:
|
|
if prev_type and prev_type != "empty":
|
|
story.append(Spacer(1, 4))
|
|
prev_type = "empty"
|
|
continue
|
|
|
|
block_type = _detect_block_type(getattr(para.style, "name", None), para)
|
|
style = _STYLE_MAP.get(block_type, _STYLE_MAP["text"])
|
|
|
|
# draw separator line before new heading sections (except first)
|
|
if block_type == "heading" and prev_type not in (None, "heading"):
|
|
story.append(Spacer(1, 6))
|
|
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#cccccc")))
|
|
|
|
prefix = "\u2022\u00a0" if block_type == "bullet" else ""
|
|
story.append(Paragraph(f"{prefix}{text}", style))
|
|
prev_type = block_type
|
|
|
|
pdf.build(story)
|
|
return buf.getvalue()
|