This commit is contained in:
Mariano Gabriel
2026-07-05 11:26:45 -03:00
parent 300806b936
commit 7b276e8f3d
6 changed files with 402 additions and 64 deletions

View File

@@ -11,9 +11,29 @@ from .base import ExtractionResult
MAX_SHEET_ROWS = 200
# Generic core-property titles Office writes by default — worse than useless as a
# display title (they hide the real one), so we drop them and derive from content.
PLACEHOLDER_TITLES = {
"word document", "powerpoint presentation", "excel workbook",
"microsoft word document", "microsoft powerpoint presentation",
"microsoft excel worksheet", "presentation", "workbook", "document",
}
def _good_title(t) -> bool:
return bool(t) and str(t).strip().lower() not in PLACEHOLDER_TITLES
def _first_line(text: str, limit: int = 120) -> str:
for ln in text.splitlines():
s = ln.lstrip("#").strip()
if s:
return s[:limit]
return ""
def _core_props(props) -> dict:
"""Common OOXML core properties → metadata (only non-empty ones).
"""Common OOXML core properties → metadata (only non-empty, non-placeholder).
python-docx/pptx expose `.author`/`.last_modified_by`; openpyxl uses
`.creator`/`.lastModifiedBy`. Each target checks both spellings.
@@ -31,6 +51,8 @@ def _core_props(props) -> dict:
for src in sources:
val = getattr(props, src, None)
if val:
if dst == "title" and not _good_title(val):
continue # skip "Word Document" & friends; derive from content
out[dst] = str(val)
break
return out
@@ -43,6 +65,10 @@ def _extract_docx(source: Path) -> ExtractionResult:
content = "\n\n".join(p for p in paras if p.strip()) + "\n"
metadata = _core_props(doc.core_properties)
metadata["paragraphs"] = len([p for p in paras if p.strip()])
if "title" not in metadata:
t = _first_line(content)
if t:
metadata["title"] = t
return ExtractionResult(content=content, metadata=metadata, extractor="office/python-docx@1")
@@ -62,6 +88,12 @@ def _extract_pptx(source: Path) -> ExtractionResult:
content = "\n\n".join(blocks) + "\n"
metadata = _core_props(prs.core_properties)
metadata["slides"] = len(prs.slides)
if "title" not in metadata and prs.slides:
# first slide's title placeholder, if any
for shape in prs.slides[0].shapes:
if shape.has_text_frame and shape.text_frame.text.strip():
metadata["title"] = shape.text_frame.text.strip()[:120]
break
return ExtractionResult(content=content, metadata=metadata, extractor="office/python-pptx@1")