# SPDX-License-Identifier: AGPL-3.0-only # Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 """Document parsing -> list[Page], one dispatch with lazy optional deps. PDFs keep per-page boundaries (``page_number``); txt/md/docx/html return a single page. ``parse(path, want_images=True)`` also returns embedded images. Heavy imports are lazy, so importing this module never fails on a missing dep. """ from __future__ import annotations import logging import os from dataclasses import dataclass from html.parser import HTMLParser logger = logging.getLogger(__name__) @dataclass(frozen = True) class Page: """A unit of extracted text. ``page_number`` is 1-based (None if N/A).""" text: str page_number: int | None = None char_count: int = 0 @dataclass(frozen = True) class ParsedImage: """A raster image embedded in a document (PDF only).""" image_bytes: bytes page_number: int | None xref: int def _page(text: str, page_number: int | None) -> Page: return Page(text = text, page_number = page_number, char_count = len(text)) class _Stripper(HTMLParser): """Collect visible text, skipping