"""Handler for importing PDF files into Obsidian.""" import shutil from pathlib import Path from utils.config import ensure_unique_path, sanitize_filename def handle_pdf(file_path: Path, vault_path: Path) -> Path: """Import a PDF file into the Obsidian vault. - Converts PDF content to a new Obsidian markdown note. - Creates a hidden folder for extracted images and the original PDF. - Embeds extracted images and links to the original PDF. """ try: import fitz # pymupdf except ImportError: raise ImportError( "PDF handling requires 'pymupdf'. Install it with:\n pip install pymupdf" ) title = sanitize_filename(file_path.stem) note_name = f"{title}.md" note_path = ensure_unique_path(vault_path / note_name) # Hidden assets folder: .{title}_assets assets_folder_name = f".{title}_assets" assets_folder = vault_path / assets_folder_name counter = 1 while assets_folder.exists(): assets_folder_name = f".{title}_assets_{counter}" assets_folder = vault_path / assets_folder_name counter += 1 assets_folder.mkdir(parents=True, exist_ok=True) # Copy original PDF into assets folder pdf_copy_name = f"{title}.pdf" pdf_copy_path = ensure_unique_path(assets_folder / pdf_copy_name) shutil.copy2(file_path, pdf_copy_path) # Open PDF and extract content + images doc = fitz.open(file_path) markdown_lines = [f"# {title}", ""] # Link to original PDF rel_pdf_path = f"{assets_folder_name}/{pdf_copy_path.name}" markdown_lines.append(f"**Original PDF:** [{pdf_copy_path.name}]({rel_pdf_path})") markdown_lines.append("") # Extract images and text per page image_entries = [] # list of (page_num, img_path, rel_path) for page_num in range(len(doc)): page = doc.load_page(page_num) # Extract images img_list = page.get_images(full=True) for img_index, img in enumerate(img_list): xref = img[0] try: base_image = doc.extract_image(xref) image_bytes = base_image["image"] ext = base_image["ext"] img_filename = f"page_{page_num + 1}_img_{img_index + 1}.{ext}" img_path = assets_folder / img_filename # Handle duplicates img_path = ensure_unique_path(img_path) img_path.write_bytes(image_bytes) rel_img = f"{assets_folder_name}/{img_path.name}" image_entries.append((page_num + 1, img_path, rel_img)) except Exception as e: print( f"[PDF] Warning: could not extract image {img_index} on page {page_num + 1}: {e}" ) # Extract text text = page.get_text() if text.strip(): markdown_lines.append(f"## Page {page_num + 1}") markdown_lines.append("") markdown_lines.append(text.strip()) markdown_lines.append("") doc.close() # Add image section if any images were extracted if image_entries: markdown_lines.append("## Extracted Images") markdown_lines.append("") for page_num, img_path, rel_img in image_entries: markdown_lines.append(f"### Page {page_num}") markdown_lines.append(f"![{img_path.name}]({rel_img})") markdown_lines.append("") note_path.write_text("\n".join(markdown_lines), encoding="utf-8") print(f"[PDF] Created note: {note_path}") print(f"[PDF] Assets folder: {assets_folder}") return note_path