Skip to content

Commit 1bda9ce

Browse files
authored
Merge pull request #137 from elong0527/refactor-render-strategies
Refactor render strategies
2 parents 98e6416 + 06f0c21 commit 1bda9ce

File tree

8 files changed

+77
-4
lines changed

8 files changed

+77
-4
lines changed

.python-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/rtflite/encoding/renderer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ def _render_column_headers(self, document: Any, page: PageContext) -> list[str]:
270270
return header_elements
271271

272272
def _render_body(self, document: Any, page: PageContext) -> list[str]:
273-
page_attrs = page.final_body_attrs or document.rtf_body
273+
page_attrs = page.final_body_attrs or page.table_attrs or document.rtf_body
274274
page_df = page.data
275275
col_widths = page.col_widths
276276

src/rtflite/encoding/unified_encoder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ def encode(self, document: Any) -> str:
125125
is_last_page=True,
126126
col_widths=col_widths,
127127
needs_header=True,
128+
table_attrs=processed_attrs,
128129
)
129130
]
130131

src/rtflite/pagination/processor.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ def _should_show_element(self, element_location: str, page: PageContext) -> bool
2929
def _apply_pagination_borders(self, document, page: PageContext) -> Any:
3030
"""Apply proper borders for paginated context following r2rtf design."""
3131

32-
# Start with a deep copy of the document's body attributes
33-
page_attrs = deepcopy(document.rtf_body)
32+
# Start with a deep copy of the page's table attributes (processed/sliced)
33+
# or document's body attributes if not available
34+
base_attrs = page.table_attrs or document.rtf_body
35+
page_attrs = deepcopy(base_attrs)
3436

3537
page_df_height = page.data.height
3638
page_df_width = page.data.width

src/rtflite/pagination/strategies/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class PageContext(BaseModel):
2828
# Content Flags
2929
needs_header: bool = True
3030

31+
# Base attributes for the table body (sliced/processed)
32+
table_attrs: TableAttributes | None = None
33+
3134
# Feature-specific Metadata (populated by strategies or processors)
3235
subline_header: dict[str, Any] | None = None
3336
pageby_header_info: dict[str, Any] | None = None

src/rtflite/pagination/strategies/defaults.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def paginate(self, context: PaginationContext) -> list[PageContext]:
4040
is_last_page=(page_num == len(page_breaks) - 1),
4141
col_widths=context.col_widths,
4242
needs_header=(context.rtf_body.pageby_header or page_num == 0),
43+
table_attrs=context.table_attrs,
4344
)
4445
)
4546

src/rtflite/pagination/strategies/grouping.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def paginate(self, context: PaginationContext) -> list[PageContext]:
5050
is_last_page=(page_num == len(page_breaks) - 1),
5151
col_widths=context.col_widths,
5252
needs_header=needs_header,
53+
table_attrs=context.table_attrs,
5354
)
5455

5556
# Add page_by header info
@@ -155,6 +156,7 @@ def paginate(self, context: PaginationContext) -> list[PageContext]:
155156
is_last_page=(page_num == len(page_breaks) - 1),
156157
col_widths=context.col_widths,
157158
needs_header=is_first or context.rtf_body.pageby_header,
159+
table_attrs=context.table_attrs,
158160
)
159161

160162
if subline_by:

tests/test_page_by_alignment.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import re
2+
3+
import polars as pl
4+
5+
import rtflite as rtf
6+
7+
8+
def test_page_by_column_alignment():
9+
"""Test that column properties are correctly aligned when page_by is used."""
10+
df = pl.DataFrame(
11+
{
12+
"section": ["-----", "Age", "Age"],
13+
"item": ["Participant in Population", " <60", " >=60"],
14+
"value": [55, 25, 30],
15+
}
16+
)
17+
18+
doc = rtf.RTFDocument(
19+
df=df,
20+
rtf_body=rtf.RTFBody(
21+
page_by="section",
22+
col_rel_width=[1],
23+
text_justification=["l", "l", "c"],
24+
border_top=["single", "", ""],
25+
border_bottom=["single", "", ""],
26+
),
27+
)
28+
29+
rtf_content = doc.rtf_encode()
30+
31+
# We look for the row containing "55" (value column) and "Participant in Population"
32+
rows = rtf_content.split("\\row")
33+
row_with_55 = None
34+
for row in rows:
35+
if "55" in row and "Participant in Population" in row:
36+
row_with_55 = row
37+
break
38+
39+
assert row_with_55 is not None, "Could not find the row with data"
40+
41+
# Check alignment for "Participant in Population"
42+
idx_part = row_with_55.find("Participant in Population")
43+
pre_part = row_with_55[:idx_part]
44+
aligns_part = re.findall(r"\\q[lcrj]", pre_part)
45+
46+
# Note: The table definition (\trowd...) also contains \trqc etc. but that's row
47+
# alignment. Cell content alignment is \ql, \qc etc. inside \pard.
48+
# Usually \pard resets, so we should see \ql inside the \pard block.
49+
# \trowd... contains \clvertalt etc. but not \ql/\qc usually (unless \clq...?)
50+
# The output shows: \pard\hyphpar0... \ql ... content.
51+
52+
assert len(aligns_part) > 0, "No alignment found for Participant"
53+
last_align_part = aligns_part[-1]
54+
assert last_align_part == "\\ql", (
55+
f"Expected \\ql for Participant, got {last_align_part}"
56+
)
57+
58+
# Check alignment for "55"
59+
idx_55 = row_with_55.find("55")
60+
pre_55 = row_with_55[:idx_55]
61+
aligns_55 = re.findall(r"\\q[lcrj]", pre_55)
62+
63+
assert len(aligns_55) > 0, "No alignment found for 55"
64+
last_align_55 = aligns_55[-1]
65+
assert last_align_55 == "\\qc", f"Expected \\qc for 55, got {last_align_55}"

0 commit comments

Comments
 (0)