import sys, re, datetime from docx import Document from docx.shared import Pt from docx.enum.text import WD_ALIGN_PARAGRAPH path = sys.argv[1]; doc = Document(path) paras = doc.paragraphs norm = lambda p: re.sub(r"\s+", " ", p.text.replace(" ", " ")).strip() title = "From Corporate Disclosures to a Russell 3000 Strategic Project Database" # --- title page: everything before the Abstract block is centred i_abs = next(i for i, p in enumerate(paras) if norm(p) == "Abstract") for p in paras[:i_abs - 1]: p.alignment = WD_ALIGN_PARAGRAPH.CENTER if norm(p) == title: for r in p.runs: r.font.size = Pt(18); r.font.bold = True elif norm(p).startswith("Identification, Measurement"): for r in p.runs: r.font.size = Pt(13) # --- move References (pandoc appends it at the end) before the appendix, as in the PDF h1 = [p for p in paras if p.style.name == "Heading 1"] refs = next(p for p in h1 if norm(p) == "References") appA = next(p for p in h1 if re.match(r"^A [A-Z]", norm(p))) body = doc.element.body; kids = list(body) i_refs, i_app = kids.index(refs._p), kids.index(appA._p) moved = [k for k in kids[i_refs:] if k.tag.endswith("}sectPr") is False] for k in moved: appA._p.addprevious(k) # --- page breaks where the LaTeX source has \newpage breaks = 0 paras[i_abs - 1].paragraph_format.page_break_before = True; breaks += 1 for p in h1: t = norm(p) if t.startswith("1 Introduction") or t == "References" or p is appA: p.paragraph_format.page_break_before = True; breaks += 1 # --- document properties cp = doc.core_properties cp.title = title cp.subject = "Identification, Measurement, Validation, and Research Applications" cp.author = "Manel Kammoun; Djerrycharli Tandjambianda; Simon-Pierre Boucher" cp.keywords = "SEC filings, text as data, corporate investment, strategic projects, information extraction, large language models, entity resolution, Russell 3000" cp.comments = "UQO Working Paper No. 0001 (FIRC-funded), Version 1.0, October 28, 2026 (working draft under validation)" cp.created = cp.modified = datetime.datetime(2026, 10, 28, 12, 0) # --- base fonts closer to the PDF (Times) from docx.oxml.ns import qn for st in doc.styles: try: if st.type == 1 and st.font is not None and (st.name == "Normal" or st.name.startswith("Heading") or st.name in ("Title", "Body Text", "First Paragraph", "Compact", "Caption", "Bibliography", "Block Text")): st.font.name = "Times New Roman" rpr = st.element.get_or_add_rPr(); rf = rpr.find(qn("w:rFonts")) if rf is None: rf = rpr.makeelement(qn("w:rFonts"), {}); rpr.append(rf) for a in ("w:ascii", "w:hAnsi", "w:eastAsia", "w:cs"): rf.set(qn(a), "Times New Roman") if st.name in ("Normal", "Body Text", "First Paragraph", "Compact"): st.font.size = Pt(12) except Exception: pass # --- wide tables: smaller font and tight cell padding so that 8-10 column tables fit the page width from docx.shared import Inches from docx.oxml import OxmlElement for sec in doc.sections: sec.left_margin = sec.right_margin = Inches(0.85) for tbl in doc.tables: ncol = max(len(r.cells) for r in tbl.rows) if ncol >= 7: size = Pt(7) if ncol >= 9 else Pt(8) tbl.autofit = True for row in tbl.rows: for cell in row.cells: for para in cell.paragraphs: para.paragraph_format.space_after = Pt(0); para.paragraph_format.space_before = Pt(0) for run in para.runs: run.font.size = size tcPr = cell._tc.get_or_add_tcPr(); mar = OxmlElement("w:tcMar") for side in ("left", "right"): el = OxmlElement(f"w:{side}"); el.set(qn("w:w"), "30"); el.set(qn("w:type"), "dxa"); mar.append(el) tcPr.append(mar) # --- proportional column widths for wide tables (pandoc emits equal 0.55-inch grid columns) TOTAL = 9792 # twips: 8.5in - 2 x 0.85in margins for tbl in doc.tables: ncol = max(len(r.cells) for r in tbl.rows) if ncol < 7: continue lens = [1] * ncol for row in tbl.rows: for j, cell in enumerate(row.cells[:ncol]): lens[j] = max(lens[j], min(28, max((len(w) for w in cell.text.split()), default=1))) weights = [max(l, 4) for l in lens]; tot = sum(weights); widths = [int(TOTAL * wgt / tot) for wgt in weights] grid = tbl._tbl.find(qn("w:tblGrid")) if grid is not None: for g, wd in zip(grid.findall(qn("w:gridCol")), widths): g.set(qn("w:w"), str(wd)) tblPr = tbl._tbl.tblPr for e in tblPr.findall(qn("w:tblW")): e.set(qn("w:type"), "dxa"); e.set(qn("w:w"), str(TOTAL)) for e in tblPr.findall(qn("w:tblLayout")): e.set(qn("w:type"), "fixed") for row in tbl.rows: for j, cell in enumerate(row.cells[:ncol]): tcPr = cell._tc.get_or_add_tcPr(); tcW = tcPr.find(qn("w:tcW")) if tcW is None: tcW = OxmlElement("w:tcW"); tcPr.insert(0, tcW) tcW.set(qn("w:type"), "dxa"); tcW.set(qn("w:w"), str(widths[j])) doc.save(path) print(f"post-processed: {i_abs-1} title-page paragraphs centred, {len(moved)} reference paragraphs moved before appendix, {breaks} page breaks, properties set")