976d90f26b
Key improvements: - Add intelligent file update checking with 30-second buffer to avoid unnecessary operations - Implement efficient PDF to PNG conversion (only when source is newer) - Add smart file copying (skip if target is up-to-date) - Create proper folder structure using plot_root/source_name pattern - Improve template with better text handling for long plot names - Add text wrapping, truncation, and hover tooltips for plot names - Remove unnecessary directory cleaning for true incremental updates - Fix title display issue (was showing '.' instead of 'Gallery') - Add comprehensive logging showing what's processed vs skipped Performance benefits: - Subsequent runs are significantly faster (only processes changed files) - Reduces ImageMagick conversions and file I/O operations - Maintains file system timing robustness with buffer delays UI improvements: - Better handling of long filenames with word wrapping - Constrained text areas prevent overlap between thumbnails - Hover tooltips show full names when truncated - Responsive grid layout maintained
185 lines
6.0 KiB
Python
185 lines
6.0 KiB
Python
import subprocess
|
|
import shutil
|
|
|
|
from pathlib import Path
|
|
from jinja2 import Environment, FileSystemLoader
|
|
from config import Config
|
|
|
|
|
|
CONFIG = Config.from_yaml("config.yaml")
|
|
|
|
env = Environment(loader=FileSystemLoader("."))
|
|
template = env.get_template("template.html")
|
|
|
|
|
|
def convert_pdf_to_png(pdf_path: Path):
|
|
png_path = pdf_path.with_suffix(".png")
|
|
|
|
# Check if PNG exists and is newer than PDF (with 30 second buffer)
|
|
if png_path.exists():
|
|
pdf_mtime = pdf_path.stat().st_mtime
|
|
png_mtime = png_path.stat().st_mtime
|
|
if png_mtime >= (pdf_mtime + 30): # 30 second buffer
|
|
# PNG is up to date, no need to convert
|
|
return
|
|
else:
|
|
print(f"PDF {pdf_path.name} is newer than PNG, reconverting...")
|
|
|
|
print(f"Converting {pdf_path} → {png_path}")
|
|
subprocess.run([
|
|
"convert",
|
|
"-density", str(CONFIG.png_dpi),
|
|
str(pdf_path),
|
|
"-quality", "95",
|
|
str(png_path)
|
|
], check=True)
|
|
|
|
|
|
def needs_update(source_file: Path, target_file: Path) -> bool:
|
|
"""Check if target file needs to be updated based on source file modification time"""
|
|
if not target_file.exists():
|
|
return True
|
|
|
|
source_mtime = source_file.stat().st_mtime
|
|
target_mtime = target_file.stat().st_mtime
|
|
|
|
# Return True if source is newer than target (with 30 second buffer)
|
|
return source_mtime > (target_mtime + 30)
|
|
|
|
|
|
def build_gallery(source_dir: Path, web_dir: Path, relative_path: Path = None):
|
|
"""
|
|
Build gallery for a directory, copying files to web directory and generating index.html
|
|
|
|
Args:
|
|
source_dir: Source directory containing PDFs
|
|
web_dir: Target web directory
|
|
relative_path: Relative path for navigation (None for root)
|
|
"""
|
|
if relative_path is None:
|
|
relative_path = Path(".")
|
|
|
|
# Ensure web directory exists
|
|
target_dir = web_dir / relative_path
|
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Find all PDFs in source directory
|
|
pdfs = sorted(source_dir.glob("*.pdf"))
|
|
items = []
|
|
|
|
for pdf in pdfs:
|
|
# Convert PDF to PNG in source directory
|
|
convert_pdf_to_png(pdf)
|
|
png_path = pdf.with_suffix(".png")
|
|
|
|
# Copy both PDF and PNG to target directory only if needed
|
|
target_pdf = target_dir / pdf.name
|
|
target_png = target_dir / png_path.name
|
|
|
|
if needs_update(pdf, target_pdf):
|
|
print(f"Copying {pdf.name} to {target_pdf}")
|
|
shutil.copy2(pdf, target_pdf)
|
|
else:
|
|
print(f"Skipping {pdf.name} (up to date)")
|
|
|
|
if png_path.exists() and needs_update(png_path, target_png):
|
|
print(f"Copying {png_path.name} to {target_png}")
|
|
shutil.copy2(png_path, target_png)
|
|
elif png_path.exists():
|
|
print(f"Skipping {png_path.name} (up to date)")
|
|
|
|
items.append({
|
|
"name": pdf.name,
|
|
"pdf_href": pdf.name,
|
|
"png_href": png_path.name
|
|
})
|
|
|
|
# Find subdirectories in source
|
|
subdirs = sorted([d.name for d in source_dir.iterdir() if d.is_dir()])
|
|
|
|
# Generate index.html in target directory
|
|
output_html = target_dir / "index.html"
|
|
|
|
# Create a meaningful title
|
|
if str(relative_path) == ".":
|
|
title = "Gallery"
|
|
else:
|
|
title = f"Gallery: {relative_path}"
|
|
|
|
with output_html.open("w") as f:
|
|
f.write(template.render(
|
|
title=title,
|
|
items=items,
|
|
subdirs=subdirs,
|
|
relpath=str(relative_path)
|
|
))
|
|
|
|
print(f"Generated {output_html}")
|
|
|
|
# Recursively process subdirectories
|
|
for subdir in subdirs:
|
|
source_subdir = source_dir / subdir
|
|
new_relative_path = relative_path / subdir
|
|
build_gallery(source_subdir, web_dir, new_relative_path)
|
|
|
|
|
|
def loop_over_sources():
|
|
web_root = Path(CONFIG.web_folder)
|
|
|
|
for source in CONFIG.sources:
|
|
print(f"Processing {source.name}: {source.path}")
|
|
if source.path.is_dir():
|
|
# Create a subdirectory based on plot_root and source name
|
|
source_web_dir = web_root / CONFIG.plot_root / source.name
|
|
build_gallery(source.path, source_web_dir)
|
|
print(f"Processed {source.name}: {source.path}")
|
|
elif source.path.suffix == ".pdf":
|
|
# For single PDF files, copy to web root with plot_root and source name as directory
|
|
source_web_dir = web_root / CONFIG.plot_root / source.name
|
|
convert_pdf_to_png(source.path)
|
|
png_path = source.path.with_suffix(".png")
|
|
|
|
# Ensure web directory exists
|
|
source_web_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Copy PDF and PNG to web directory only if needed
|
|
target_pdf = source_web_dir / source.path.name
|
|
target_png = source_web_dir / png_path.name
|
|
|
|
if needs_update(source.path, target_pdf):
|
|
print(f"Copying {source.path.name} to {target_pdf}")
|
|
shutil.copy2(source.path, target_pdf)
|
|
else:
|
|
print(f"Skipping {source.path.name} (up to date)")
|
|
|
|
if png_path.exists() and needs_update(png_path, target_png):
|
|
print(f"Copying {png_path.name} to {target_png}")
|
|
shutil.copy2(png_path, target_png)
|
|
elif png_path.exists():
|
|
print(f"Skipping {png_path.name} (up to date)")
|
|
|
|
# Create items list for template
|
|
items = [{
|
|
"name": source.path.name,
|
|
"pdf_href": source.path.name,
|
|
"png_href": png_path.name
|
|
}]
|
|
|
|
# Generate index.html for single PDF
|
|
output_html = source_web_dir / "index.html"
|
|
with output_html.open("w") as f:
|
|
f.write(template.render(
|
|
title=source.name,
|
|
items=items,
|
|
subdirs=[],
|
|
relpath=source.name
|
|
))
|
|
|
|
print(f"Generated {output_html}")
|
|
print(f"Processed {source.name}: {source.path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
loop_over_sources()
|
|
print("Done")
|