From aa5bf980cd2792a9b9060db8f1621592faa862e6 Mon Sep 17 00:00:00 2001 From: linearcombination <4829djaskdfj@gmail.com> Date: Thu, 20 Aug 2026 17:02:41 -0700 Subject: [PATCH] Use Mm rather than Inches for A4 dimensions Update based on similar changes made to STET as brought to attention by PR code review. --- backend/passages/domain/document_generator.py | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/backend/passages/domain/document_generator.py b/backend/passages/domain/document_generator.py index 841d7334..bb4c5418 100644 --- a/backend/passages/domain/document_generator.py +++ b/backend/passages/domain/document_generator.py @@ -1,6 +1,6 @@ import json import time -from typing import Mapping, Optional, Sequence, TYPE_CHECKING +from typing import TYPE_CHECKING, Mapping, Optional, Sequence from celery import current_task from doc.config import settings @@ -19,17 +19,17 @@ resource_types, ) from doc.reviewers_guide.model import BibleReference +from doc.utils.docx_util import ensure_reference_styles from doc.utils.file_utils import docx_filepath, file_needs_update from doc.utils.text_utils import maybe_correct_book_name -from doc.utils.docx_util import ensure_reference_styles from docx import Document from docx.oxml import parse_xml -from docx.shared import Inches, RGBColor +from docx.shared import Length, Mm, Pt, RGBColor from docx.table import _Cell, _Row from html4docx import HtmlToDocx # type: ignore from passages.domain.model import ( - Passage, BibleReferenceWithAvailability, + Passage, ) from passages.domain.parser import split_chapter_into_verses, verse_text_html from passages.domain.stet_verse_list_parser import BOOK_INDEX, parse_bible_blocks @@ -245,13 +245,21 @@ def generate_docx( available_reference_style_name: str = "AvailableReference", unavailable_reference_style_name: str = "UnavailableReference", unavailable_color: RGBColor = UNAVAILABLE_COLOR, - total_width: int = Inches(7.0), - document_margin_width: float = Inches(0.75), + document_margin_width: Length = Pt(54), + a4_width: Length = Mm(210), + a4_height: Length = Mm(297), ) -> None: doc = Document() section = doc.sections[0] - section.left_margin = Inches(0.75) - section.right_margin = Inches(0.75) + # Explicitly set A4 paper size and uniform margins + section.page_width = a4_width + section.page_height = a4_height + section.left_margin = document_margin_width + section.right_margin = document_margin_width + section.top_margin = document_margin_width + section.bottom_margin = document_margin_width + # Calculate exact printable area dynamically from margins (EMU level precision) + printable_width_emu: int = int(a4_width) - (2 * int(document_margin_width)) ensure_reference_styles(doc, unavailable_color=unavailable_color) html_to_docx = HtmlToDocx() has_lang1 = lang1_code is not None and lang1_name is not None @@ -265,16 +273,26 @@ def generate_docx( columns.append("lang1") if show_notes_column: columns.append("notes") + # Proportionally split printable width so columns perfectly fill the margin bounds if columns == ["lang0"]: - col_widths = [total_width] + col_widths = [Length(printable_width_emu)] elif columns == ["lang0", "lang1"]: - col_widths = [Inches(3.5), Inches(3.5)] + w = Length(int(printable_width_emu * 0.50)) + col_widths = [w, w] elif columns == ["lang0", "notes"]: - col_widths = [Inches(4.5), Inches(2.5)] + col_widths = [ + Length(int(printable_width_emu * 0.65)), + Length(int(printable_width_emu * 0.35)), + ] elif columns == ["lang0", "lang1", "notes"]: - col_widths = [Inches(3.0), Inches(3.0), Inches(1.0)] + col_widths = [ + Length(int(printable_width_emu * 0.425)), + Length(int(printable_width_emu * 0.425)), + Length(int(printable_width_emu * 0.15)), + ] else: logger.warning(f"Unexpected column configuration: {columns}") + col_widths = [Length(int(printable_width_emu / len(columns)))] * len(columns) table = doc.add_table(rows=0, cols=len(columns)) table.autofit = False table.allow_autofit = False @@ -288,6 +306,9 @@ def generate_docx( ) for p0, p1 in pairs: row = table.add_row() + # Apply explicit column widths to cells in each row to prevent Word layout collapse + for i, w in enumerate(col_widths): + row.cells[i].width = w cell = row.cells[col_index["lang0"]] run = cell.add_paragraph().add_run(p0.localized_reference) run.style = (