fix(ci): resolve Pillow JPEG KeyError and cairosvg missing dep

convert.py: Pillow's PDF writer requires libjpeg for RGB images, which
is not available in the CI Python environment. Replace all Pillow PDF
saves with _save_images_as_pdf(), which writes pages as lossless PNGs
and assembles them with qpdf — no JPEG dependency needed.

build.yml: install mkdocs-material[imaging] instead of mkdocs-material
to satisfy the cairosvg dependency required by the social plugin.

Signed-off-by: nopeitsnothing <no@anonymousplanet.org>
This commit is contained in:
nopeitsnothing
2026-05-22 17:21:44 -04:00
parent f9d4c17ac6
commit 823edbf4af
2 changed files with 24 additions and 7 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
python-version: "3.13"
- name: 📦 Install Python dependencies
run: pip install mkdocs-material pillow numpy
run: pip install "mkdocs-material[imaging]" pillow numpy
- name: 🖼️ Install poppler and qpdf
run: |
+23 -6
View File
@@ -92,6 +92,27 @@ def apply_dark_theme(
return Image.fromarray((out * 255).clip(0, 255).astype('uint8'))
def _save_images_as_pdf(images: list, output_path: str) -> None:
"""Save a list of RGB PIL images as a PDF using PNG compression via qpdf.
Pillow's built-in PDF writer defaults to JPEG encoding for RGB images,
which fails when libjpeg is not available in the environment. Instead we
write each page as a lossless PNG to a temp directory and assemble them
with qpdf, which embeds the PNGs directly without re-encoding.
"""
import tempfile as _tempfile
with _tempfile.TemporaryDirectory() as staging:
png_paths = []
for i, img in enumerate(images):
p = os.path.join(staging, f'p{i:05d}.png')
img.save(p, format='PNG')
png_paths.append(p)
subprocess.run(
['qpdf', '--empty', '--pages'] + png_paths + ['--', output_path],
check=True,
)
def _check_qpdf() -> bool:
return subprocess.run(
['qpdf', '--version'], capture_output=True
@@ -163,7 +184,7 @@ def convert_pdf_to_dark(
)
dark = [apply_dark_theme(Image.open(p), bg, text, link) for p in batch]
dark[0].save(batch_path, save_all=True, append_images=dark[1:])
_save_images_as_pdf(dark, batch_path)
batch_files.append(batch_path)
del dark
@@ -182,11 +203,7 @@ def convert_pdf_to_dark(
print(f" Page {i}/{total}", flush=True)
dark_pages.append(apply_dark_theme(Image.open(p), bg, text, link))
dark_pages[0].save(
output_path,
save_all=True,
append_images=dark_pages[1:],
)
_save_images_as_pdf(dark_pages, output_path)
size_mb = os.path.getsize(output_path) / 1024 / 1024
print(f" Saved → {output_path} ({size_mb:.1f} MB)")