99 lines
3.5 KiB
Python
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"")
|
|
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
|