The cover is a full-bleed mosaic of historical Bengali types filling the word ব্যঞ্জণ, produced by tools/gen_cover_mosaic.py from plates/ and fonts/ alone (build.sh remakes it if missing). It is static, so ebook readers can cache it. The mark on the About this edition page is drawn by tools/gen_seal.py, seeded from a SHA-256 of src/ (never the build's own outputs), so it changes exactly when the transcription does. The colophon is shortened to name the cover typefaces and the mark's mechanism, and drops the trailing ProQuest note. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
49 lines
3.3 KiB
Bash
Executable File
49 lines
3.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# Assemble: preamble, title (p0001), colophon, remaining pages in PDF-page order,
|
|
# endnotes; compile with XeLaTeX (3 passes: marks/backrefs).
|
|
set -e
|
|
cd "$(dirname "$0")"
|
|
OUT=ross-1988-retypeset.pdf
|
|
# Two builds must never share work/: they share main.aux, and the second reads
|
|
# the first's half-written copy and dies at \begin{document} with "Undefined
|
|
# control sequence" or "File ended while scanning use of \enotez@note" — which
|
|
# reads like an unbalanced brace in a page file and is nothing of the kind.
|
|
# mkdir is atomic, so it is the lock. The way a second build actually gets
|
|
# started is mundane: someone runs `make` again while an earlier build is still
|
|
# going. Check `docker ps` before starting one — a build takes several minutes
|
|
# and gives no output until it finishes, so a running one is easy to forget.
|
|
if ! mkdir work/.buildlock 2>/dev/null; then
|
|
echo "build.sh: another build holds work/.buildlock — refusing to start." >&2
|
|
echo " check: docker ps (if nothing is running: rmdir work/.buildlock)" >&2
|
|
exit 1
|
|
fi
|
|
trap 'rmdir work/.buildlock 2>/dev/null' EXIT INT TERM
|
|
# Three full passes run below regardless, so a stale aux buys nothing.
|
|
rm -f work/main.aux work/main.toc work/main.out
|
|
python3 tools/polish.py >/dev/null # typographic pass: src/pages -> work/pages
|
|
# Version seal: a mark generated from a hash of the sources, drawn in the
|
|
# colophon. Regenerated here so the PDF can never carry a stale one. The hash
|
|
# covers src/ only -- never main.tex, work/seal.tex or the PDF, all of which
|
|
# this build produces, which would make the seed depend on its own output.
|
|
python3 tools/gen_seal.py --content >/dev/null
|
|
# Cover mosaic. Tracked at plates/cover-mosaic.png so an ordinary build is
|
|
# fast, but remade here if it is missing, so the cover survives losing any
|
|
# derived file -- the generator needs only plates/ and fonts/, both in git.
|
|
[ -f plates/cover-mosaic.png ] || python3 tools/gen_cover_mosaic.py
|
|
# Re-encode the plates to match what they actually hold: bilevel type goes to
|
|
# lossless JBIG2, genuine halftone stays 8-bit as JPEG. Writes copies under
|
|
# work/plates-opt and repoints work/pages at them -- plates/ and src/ are
|
|
# never touched, so deleting work/ reverts it. Must run AFTER polish.py, which
|
|
# is what creates work/pages.
|
|
python3 tools/optimize_plates.py
|
|
{ cat src/preamble.tex
|
|
printf '%s\n' '\begin{document}\immediate\openout\unsurefile=unsure.log\immediate\openout\erratafile=errata.log\immediate\openout\qslipfile=qslips.log'
|
|
printf '\\input{%s}\n' src/cover.tex work/pages/p0001.tex src/colophon.tex
|
|
for f in work/pages/p*.tex; do [ "$f" = work/pages/p0001.tex ] || printf '\\input{%s}\n' "$f"; done
|
|
printf '%s\n' '\notesection' '\printerrata' '\immediate\closeout\unsurefile\immediate\closeout\erratafile\immediate\closeout\qslipfile\end{document}'
|
|
} > src/main.tex
|
|
for i in 1 2; do xelatex -interaction=nonstopmode -halt-on-error -output-directory=work src/main.tex >work/pass$i.log 2>&1 || { grep -E "^!" -A3 work/pass$i.log; exit 1; }; done
|
|
xelatex -interaction=nonstopmode -halt-on-error -output-directory=work src/main.tex | grep -E "Overfull|Warning: .*(undefined|multiply)" | sort | uniq -c || true
|
|
cp work/main.pdf "$OUT"; cp work/unsure.log . 2>/dev/null || true; cp work/errata.log . 2>/dev/null || true; cp work/qslips.log . 2>/dev/null || true
|
|
echo "built $OUT: $(pdfinfo "$OUT" | grep Pages)"
|