()
| 616 | |
| 617 | # ===================== 主流程 ===================== |
| 618 | def build(): |
| 619 | OUTPUT_DIR.mkdir(parents=True, exist_ok=True) |
| 620 | |
| 621 | data = json.loads(JSON_PATH.read_text(encoding="utf-8")) |
| 622 | meta = data.get("meta", {}) or {} |
| 623 | sections_all = data.get("sections", []) or [] |
| 624 | sections = [s for s in sections_all if norm_title(s.get("title","")) != norm_title("Poster Title & Author")] |
| 625 | |
| 626 | panels_by_id, figures, cap_full, cap_base = load_arrangement_and_captions() |
| 627 | print(f"✅ Loaded arrangement and captions.") |
| 628 | sample_paths = [pathlib.Path(f.get("figure_path","")) for f in figures if f.get("figure_path")] |
| 629 | images_parent = resolve_images_parent_dir(sample_paths) |
| 630 | |
| 631 | template = TEMPLATE_PATH.read_text(encoding="utf-8") |
| 632 | |
| 633 | # 头部 |
| 634 | t, a, inst, wrapped_title = build_header_from_meta(meta) |
| 635 | new_tex = template |
| 636 | new_tex = replace_command_balanced(new_tex, "title", t) |
| 637 | new_tex = replace_command_balanced(new_tex, "author", a) |
| 638 | new_tex = replace_command_balanced(new_tex, "institute", inst) |
| 639 | |
| 640 | # 放大 scale + 动态标题字号 + 右上角 logo |
| 641 | new_tex = bump_beamerposter_scale(new_tex, BEAMER_SCALE_TARGET) |
| 642 | dyn_title_size = choose_title_size_cmd(wrapped_title) # <-- 多行则调小 |
| 643 | new_tex = inject_font_tweaks(new_tex, dyn_title_size) |
| 644 | new_tex = inject_right_logo(new_tex) |
| 645 | |
| 646 | # blocks(带“按预算缩放”的图 + 清洗后的 caption) |
| 647 | secidx_to_figs = build_figures_for_sections(sections, panels_by_id, figures, cap_full, cap_base) |
| 648 | blocks = [] |
| 649 | for i, sec in enumerate(sections): |
| 650 | figs_tex = figures_to_latex(secidx_to_figs.get(i, []), OUTPUT_PATH, images_parent) if secidx_to_figs.get(i) else "" |
| 651 | blocks.append(make_block(sec.get("title",""), sec.get("content",""), figs_tex)) |
| 652 | |
| 653 | # 三列连续均匀切分 |
| 654 | new_tex = rebuild_first_columns_region_to_three(new_tex, blocks) |
| 655 | # --- 后处理:清理多余转义 --- |
| 656 | cleaned_tex = new_tex |
| 657 | cleaned_tex = cleaned_tex.replace(r"\{", "{") |
| 658 | cleaned_tex = cleaned_tex.replace(r"\}", "}") |
| 659 | # 注意:要先处理上面的大括号再处理反斜杠,否则会提前破坏结构 |
| 660 | cleaned_tex = cleaned_tex.replace(r"\\\\", r"\\") # 避免双转义干扰 |
| 661 | cleaned_tex = cleaned_tex.replace(r"\\", "\\") # 最终将 \\ → \ |
| 662 | cleaned_tex = cleaned_tex.replace(r"\t\t", "\\t") |
| 663 | cleaned_tex = strip_stray_t(cleaned_tex) |
| 664 | |
| 665 | OUTPUT_PATH.write_text(cleaned_tex, encoding="utf-8") |
| 666 | print(f"✅ Wrote: {OUTPUT_PATH.relative_to(ROOT_DIR)}") |
| 667 | print(f"📁 Figures copied to: {OUTPUT_DIR / 'figures'}") |
| 668 | print(f"🔠 Title size chosen: {dyn_title_size}") |
| 669 | |
| 670 | if __name__ == "__main__": |
| 671 | build() |
no test coverage detected