The .tex is no longer stale: regenerated from the canonical .md by build_tex.py (pandoc 3.1.3 + pdflatex on the server; marked GENERATED, never edited by hand). PDF: 28 pages, 0 errors, 0 undefined references, 0 overfull boxes. For LaTeX the .md got braces on four n_\max subscripts (fix_md_for_latex.py; rendering identical) and Table 10 was split into totals (10) and per-problem counts (10b) so that it fits a page; numbers unchanged. verify_article on the server 467 OK / 0 BAD; regression x2 1226 passed, 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""Regenerate article/sim_numerics.tex (and the PDF) from the canonical article/sim_numerics.md.
|
||||
|
||||
The .md is the text; the .tex is a build product and is never edited by hand. Title, author
|
||||
and abstract become pandoc metadata; the body is converted as it stands (section numbers are
|
||||
part of the headings, so LaTeX numbering is off). Unicode that pdflatex does not know is
|
||||
declared in the header. Run on the server (pandoc 3.1.3, pdflatex):
|
||||
|
||||
python -u build_tex.py -> article/sim_numerics.tex, article/sim_numerics.pdf
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
MD = "article/sim_numerics.md"
|
||||
TEX = "article/sim_numerics.tex"
|
||||
|
||||
HEADER = r"""
|
||||
\usepackage{amsmath,amssymb}
|
||||
\usepackage{textcomp}
|
||||
\DeclareUnicodeCharacter{2032}{\ensuremath{'}}
|
||||
\DeclareUnicodeCharacter{2212}{\ensuremath{-}}
|
||||
\DeclareUnicodeCharacter{00D7}{\ensuremath{\times}}
|
||||
\DeclareUnicodeCharacter{00B5}{\textmu}
|
||||
\DeclareUnicodeCharacter{2192}{\ensuremath{\rightarrow}}
|
||||
\DeclareUnicodeCharacter{0394}{\ensuremath{\Delta}}
|
||||
\DeclareUnicodeCharacter{2082}{\textsubscript{2}}
|
||||
\usepackage[margin=2.5cm]{geometry}
|
||||
\usepackage[htt]{hyphenat}
|
||||
\setlength{\emergencystretch}{3em}
|
||||
\usepackage{etoolbox}
|
||||
\AtBeginEnvironment{longtable}{\small}
|
||||
"""
|
||||
|
||||
BANNER = ("%% GENERATED from article/sim_numerics.md by build_tex.py - do not edit by hand.\n"
|
||||
"%% The .md is the canonical text; every number in it is checked by verify_article.py.\n")
|
||||
|
||||
|
||||
def split_front(md):
|
||||
lines = md.split("\n")
|
||||
title = lines[0].lstrip("# ").strip()
|
||||
rest = lines[1:]
|
||||
author = next(ln.strip() for ln in rest if ln.strip())
|
||||
text = "\n".join(rest)
|
||||
head, _, body = text.partition("## Abstract")
|
||||
abstract, _, body = body.partition("\n---\n")
|
||||
return title, author, abstract.strip(), body.lstrip("\n")
|
||||
|
||||
|
||||
def main():
|
||||
with open(MD, encoding="utf8") as fh:
|
||||
title, author, abstract, body = split_front(fh.read())
|
||||
meta = {"title": title, "author": author, "abstract": abstract,
|
||||
"header-includes": HEADER, "documentclass": "article",
|
||||
"classoption": ["11pt", "a4paper"]}
|
||||
os.makedirs("build", exist_ok=True)
|
||||
with open("build/meta.json", "w", encoding="utf8") as fh:
|
||||
json.dump(meta, fh)
|
||||
with open("build/body.md", "w", encoding="utf8") as fh:
|
||||
fh.write(body)
|
||||
subprocess.run(["pandoc", "build/body.md", "--metadata-file=build/meta.json", "-s",
|
||||
"-f", "markdown+tex_math_dollars+pipe_tables", "-t", "latex",
|
||||
"-o", "build/body.tex"], check=True)
|
||||
with open("build/body.tex", encoding="utf8") as fh:
|
||||
tex = fh.read()
|
||||
with open(TEX, "w", encoding="utf8") as fh:
|
||||
fh.write(BANNER + tex)
|
||||
for _ in range(2):
|
||||
r = subprocess.run(["pdflatex", "-interaction=nonstopmode", "-halt-on-error",
|
||||
"-output-directory", "article", TEX],
|
||||
capture_output=True, text=True)
|
||||
log = open("article/sim_numerics.log", encoding="utf8", errors="replace").read()
|
||||
errors = [ln for ln in log.splitlines() if ln.startswith("!")]
|
||||
# only undefined references / citations count; 'Font shape ... undefined' is a font
|
||||
# substitution warning, not a defect of the text
|
||||
undefined = [ln for ln in log.splitlines()
|
||||
if "undefined" in ln.lower() and ("reference" in ln.lower()
|
||||
or "citation" in ln.lower())]
|
||||
overfull = sum(1 for ln in log.splitlines() if ln.startswith("Overfull"))
|
||||
pages = next((ln for ln in log.splitlines() if "Output written" in ln), "no output")
|
||||
print(f"pdflatex exit {r.returncode}; errors {len(errors)}; undefined {len(undefined)}; "
|
||||
f"overfull boxes {overfull}")
|
||||
for ln in errors[:10] + undefined[:10]:
|
||||
print(" ", ln)
|
||||
print(pages)
|
||||
print("build done")
|
||||
sys.exit(0 if r.returncode == 0 and not errors else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user