"""CV text cleanup helpers for the PDF extractor. Pure module: no FastAPI imports and no HTTPException. Designer-made resumes position every glyph individually, so pypdf hands back "S K I L L S" instead of "SKILLS". In that layout a single space is glyph padding and a run of two or more spaces is the real word gap, which is what the `despace_line` decorator keys off to rebuild readable lines. """ from __future__ import annotations import re from job.candidate.decorators import despace_line, normalize_unicode @normalize_unicode @despace_line def normalize_spaced_text(text) -> str: """Turn raw pypdf output into readable text, leaving normal lines untouched. The decorators have already folded the unicode and rebuilt the glyph-padded lines; what is left is the whitespace tidy-up that every line wants. """ if not text: return "" lines = [re.sub(r" {2,}", " ", line).strip() for line in text.splitlines()] return re.sub(r"\n{3,}", "\n\n", "\n".join(lines)).strip()