from pathlib import Path
import subprocess,sys,json,hashlib,re,math
root=Path(__file__).resolve().parents[1]
kind=sys.argv[1]
stem={'main':'490d_Chronological_Families_Explanation_C1431','technical':'490d_Technical_Companion_C1431'}[kind]
src=root/'deliverables'/(stem+'.md');dest=root/'deliverables'/(stem+'_Print.pdf')
work=root/'prep'/'render';work.mkdir(exist_ok=True)
portable_map=root/'assets'/'Chronological_Families_Map.png'
lines=src.read_text().splitlines();title=lines[0][2:];body='\n'.join(lines[1:]).lstrip().replace('sandbox:','')
if portable_map.exists():
body=re.sub(r'(!\[Six source routes[^\]]*\]\()[^)]+(\))',lambda m:m.group(1)+str(portable_map)+m.group(2),body)
if kind=='main':
start=body.index('![Six source routes');stop=body.index('## Local changes become',start)
body=body[:start]+'\\clearpage\n\n'+body[start:stop]+'\\clearpage\n\n'+body[stop:]
# Start the comparative chapter on a fresh page; its source summary is self-contained.
body=body.replace('## The same spine operation in LXX and SP','\\clearpage\n\n## The same spine operation in LXX and SP')
body=body.replace('## How the three inverse families connect internally','\\clearpage\n\n## How the three inverse families connect internally')
body=body.replace('## Babylonian spans connect the inverse, Covenant and calendar families',r'\clearpage'+'\n\n## Babylonian spans connect the inverse, Covenant and calendar families')
# Keep short comparative tables and equation lead-ins readable across page breaks.
body=re.sub(r'(?m)^(### .+)$',lambda m:r'\Needspace{5\baselineskip}'+'\n\n'+m.group(1),body)
blocks=body.split('\n\n')
for i,block in enumerate(blocks):
if block.lstrip().startswith('\\[') and i and not blocks[i-1].lstrip().startswith(('|','#','\\')):
n=min(13,math.ceil(len(blocks[i-1])/90)+4)
blocks[i-1]='\\Needspace{'+str(n)+r'\baselineskip}'+'\n\n'+blocks[i-1]
if block.lstrip().startswith('|') and len(block.splitlines())<=11:
blocks[i]='\\Needspace{18'+r'\baselineskip}'+'\n\n'+block
body='\n\n'.join(blocks)
if kind=='technical':
body=body.replace('## 4. Original-span register theorem',r'\clearpage'+'\n\n## 4. Original-span register theorem')
prepared=work/(kind+'.md');prepared.write_text(body)
header=work/'header.tex';header.write_text(r'''\let\oldtableofcontents\tableofcontents
\renewcommand{\tableofcontents}{\oldtableofcontents\clearpage}
\usepackage{etoolbox}
\usepackage{needspace}
\AtBeginEnvironment{longtable}{\small}
\AtBeginEnvironment{equation*}{\Needspace{3\baselineskip}}
\emergencystretch=3em
''')
cmd=['pandoc',str(prepared),'-f','markdown+tex_math_single_backslash','--standalone','--pdf-engine=xelatex','--toc','--toc-depth=2','-V','mainfont=DejaVu Serif','-V','sansfont=DejaVu Sans','-V','mathfont=Latin Modern Math','-V','monofont=DejaVu Sans Mono','-V','fontsize=10pt','-V','geometry:margin=0.7in','-V','linestretch=1.08','-V','papersize=a4','-M','title='+title,'-M','date=September 29, 2026 UTC — comparison through C1582','--include-in-header='+str(header),'-o',str(dest)]
r=subprocess.run(cmd,text=True,capture_output=True);(work/(kind+'.log')).write_text(r.stdout+r.stderr)
if r.returncode:print(r.stderr);raise SystemExit(r.returncode)
print(json.dumps({'kind':kind,'pdf':str(dest),'bytes':dest.stat().st_size,'warnings':r.stderr}))
Evidence
Keep short comparative tables and equation lead-ins readable across page breaks.
Edition and provenance
render_readers.py
SHA-256 125c584ac5c6d6d5e15783176e7505f3a2d97714f8448019a805a159d9519c89
C480–C1634/Research_Cycles/C1483_C1582/c1483_c1582/prep/render_readers.py