Files
2026-05-26 14:27:01 +02:00

99 lines
3.5 KiB
Python

"""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