File size: 3,446 Bytes
c732cdb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Document Parser supporting TXT, Markdown, PDF, DOCX, and raw strings.
"""

from pathlib import Path
from typing import Union
import pymupdf  # PyMuPDF
import docx
import pptx
import openpyxl


def extract_text_from_file(file_path: Union[str, Path]) -> str:
    """Extract plain text from various file formats (.txt, .md, .pdf, .docx)."""
    path = Path(file_path)
    if not path.is_file():
        raise FileNotFoundError(f"File not found: {path}")

    ext = path.suffix.lower()

    if ext in [".txt", ".md", ".markdown", ".rtf", ".rst", ".py", ".json", ".csv"]:
        return path.read_text(encoding="utf-8", errors="replace")

    elif ext == ".pdf":
        text_parts = []
        with pymupdf.open(str(path)) as doc:
            for page in doc:
                t = page.get_text()
                if t:
                    text_parts.append(t)
        return "\n\n".join(text_parts).strip()

    elif ext in [".docx", ".doc"]:
        if ext == ".doc":
            # Best effort try python-docx or raw read
            try:
                doc = docx.Document(str(path))
                return "\n".join([p.text for p in doc.paragraphs if p.text]).strip()
            except Exception:
                return path.read_text(encoding="utf-8", errors="replace")
        doc = docx.Document(str(path))
        paragraphs = [p.text for p in doc.paragraphs if p.text]
        # Also parse tables if present
        for table in doc.tables:
            for row in table.rows:
                row_text = " | ".join([cell.text.strip() for cell in row.cells if cell.text.strip()])
                if row_text:
                    paragraphs.append(row_text)
        return "\n".join(paragraphs).strip()

    elif ext in [".pptx", ".ppt"]:
        prs = pptx.Presentation(str(path))
        text_runs = []
        for slide_idx, slide in enumerate(prs.slides, 1):
            slide_texts = []
            for shape in slide.shapes:
                if shape.has_text_frame:
                    for paragraph in shape.text_frame.paragraphs:
                        p_text = "".join(run.text for run in paragraph.runs).strip()
                        if p_text:
                            slide_texts.append(p_text)
                elif shape.has_table:
                    for row in shape.table.rows:
                        row_text = " | ".join(cell.text.strip() for cell in row.cells if cell.text.strip())
                        if row_text:
                            slide_texts.append(row_text)
            if slide_texts:
                text_runs.append(f"--- Slide {slide_idx} ---\n" + "\n".join(slide_texts))
        return "\n\n".join(text_runs).strip()

    elif ext in [".xlsx", ".xlsm", ".xltx"]:
        wb = openpyxl.load_workbook(str(path), data_only=True)
        sheet_texts = []
        for sheet_name in wb.sheetnames:
            ws = wb[sheet_name]
            rows_text = []
            for row in ws.iter_rows(values_only=True):
                non_empty = [str(cell).strip() for cell in row if cell is not None and str(cell).strip()]
                if non_empty:
                    rows_text.append(" | ".join(non_empty))
            if rows_text:
                sheet_texts.append(f"--- Sheet: {sheet_name} ---\n" + "\n".join(rows_text))
        return "\n\n".join(sheet_texts).strip()

    else:
        # Default fallback to plain text read
        return path.read_text(encoding="utf-8", errors="replace")