Files
old-books/_pipeline/figures.py
T
2026-10-17 15:27:14 -05:00

72 lines
3.4 KiB
Python

"""Figures: find every image in the chapters being processed and list it in figures/skipped_figures.md.
Figures support the concept only (R7). Nothing is spoken unless a spoken sentence is approved, and none is yet,
so every figure is listed as skipped."""
import os
import re
import pageparts
import pdftext
import structure
def toc_pictures(units, before_unit):
"""Picture list in the table of contents: [(caption, book_page)]."""
lines = []
for u in units[:before_unit]:
lines += u["text"].split("\n")
out = []
for ln in lines:
m = re.match(r"^\s*([A-Z][A-Z .,'\-—]+?)\s*\.{3,}\s*(\d+)(?:\s*-\s*\d+)?\s*$", ln)
if m:
out.append((m.group(1).strip(), int(m.group(2))))
return out
def run(book_dir, book, pdf, chapter_numbers):
"""Writes figures/skipped_figures.md. Returns warnings."""
units = pdftext.units(pdf)
heads = structure.find_headings(units)
pages, _ = structure.book_pages(units, book["title"])
toc = toc_pictures(units, heads[0]["unit"])
imgs = pdftext.images(pdf)
rows, warnings = [], []
for ch in book["chapters"]:
if ch["number"] not in chapter_numbers:
continue
lo, hi = ch["pdf_pages"]
for im in imgs:
if not lo <= im["pdf_page"] <= hi:
continue
ui = next(i for i, u in enumerate(units) if u["pdf_page"] == im["pdf_page"] and u["half"] == im["half"])
caption, source = None, None
for u in units:
if u["pdf_page"] == im["pdf_page"]:
for ln in u["text"].split("\n"):
m = pageparts.CAPTION_RE.match(ln)
if m:
caption, source = m.group(2).title(), "caption printed on the page (%s)" % ln.strip()
if caption is None:
hit = [c for c, p in toc if p == pages[ui]]
if hit:
caption, source = hit[0].title(), "table of contents picture list, page %d" % pages[ui]
if caption is None:
warnings.append(("figure-no-caption", "pdf p.%d%s" % (im["pdf_page"], im["half"] or ""), "no caption found"))
rows.append((ch["number"], im, pages[ui], caption, source))
os.makedirs(os.path.join(book_dir, "figures"), exist_ok=True)
out = ["# Skipped figures", "",
"Figures support the concept only, and nothing in a figure is read aloud unless a spoken sentence is approved.",
"No spoken figure sentence is approved for this book yet, so every figure below is skipped.", "",
"Scope: chapters %s." % ", ".join(str(n) for n in sorted(chapter_numbers)), ""]
for n, im, bp, caption, source in rows:
out += ["- Chapter %d, pdf page %d (%s half), book page %s: image %d x %d pt on the page." % (
n, im["pdf_page"], {"L": "left", "R": "right", None: "whole"}[im["half"]], bp if bp and bp >= 1 else "unnumbered",
im["width"], im["height"]),
" Caption: %s." % (caption or "none found"),
" Caption source: %s." % (source or "none"),
" Reason skipped: no approved spoken sentence."]
if not rows:
out.append("No figures found in these chapters.")
with open(os.path.join(book_dir, "figures", "skipped_figures.md"), "w", encoding="utf-8") as f:
f.write("\n".join(out) + "\n")
return warnings