fix table in cell wrapping
Python CI / test (3.10) (push) Successful in 2m17s
Python CI / test (3.13) (push) Has been cancelled
Python CI / test (3.12) (push) Has been cancelled

This commit is contained in:
2025-11-10 15:15:03 +01:00
parent 5afad2ca07
commit 8e720d4037
7 changed files with 499 additions and 15 deletions
+39 -15
View File
@@ -145,17 +145,36 @@ class TableCellRenderer(Box):
block, x, current_y, width, height - (current_y - y))
elif isinstance(block, (Paragraph, Heading)):
# Get words from the block
from pyWebLayout.abstract.inline import Word as AbstractWord
word_items = block.words() if callable(block.words) else block.words
words = list(word_items)
if not words:
continue
# Create new Word objects with the table cell's font
# The words from the paragraph may have AbstractStyle, but we need Font objects
wrapped_words = []
for word_item in words:
# Handle word tuples (index, word_obj)
if isinstance(word_item, tuple) and len(word_item) >= 2:
word_obj = word_item[1]
else:
word_obj = word_item
# Extract text from the word
word_text = word_obj.text if hasattr(word_obj, 'text') else str(word_obj)
# Create a new Word with the cell's Font
new_word = AbstractWord(word_text, font)
wrapped_words.append(new_word)
# Layout words using Line objects with wrapping
word_index = 0
pretext = None
while word_index < len(words):
while word_index < len(wrapped_words):
# Check if we have space for another line
if current_y + ascent + descent > y + available_height:
break # No more space in cell
@@ -172,29 +191,29 @@ class TableCellRenderer(Box):
# Add words to this line until it's full
line_has_content = False
while word_index < len(words):
word = words[word_index]
# Handle word tuples (index, word_obj)
if isinstance(word, tuple) and len(word) >= 2:
word_obj = word[1]
else:
word_obj = word
while word_index < len(wrapped_words):
word = wrapped_words[word_index]
# Try to add word to line
success, overflow = line.add_word(word_obj, pretext)
success, overflow = line.add_word(word, pretext)
pretext = None # Clear pretext after use
if success:
line_has_content = True
if overflow:
# Word was hyphenated, carry over to next line
# DON'T increment word_index - we need to add the overflow
# to the next line with the same word
pretext = overflow
word_index += 1
break # Move to next line
else:
# Word fit completely, move to next word
word_index += 1
else:
# Word doesn't fit on this line
if not line_has_content:
# Even first word doesn't fit, force it anyway to avoid infinite loop
# Even first word doesn't fit, force it anyway and advance
# This prevents infinite loops with words that truly can't fit
word_index += 1
break
@@ -454,11 +473,16 @@ class TableRenderer(Box):
column_widths = [column_width] * num_columns
# Calculate row heights
header_height = 35 if any(1 for section,
# Minimum height needs to account for:
# - Font size (12px) + line height (4px) = 16px per line
# - Cell padding (varies, but typically 10-20px top+bottom)
# - At least 2 lines of text for wrapping
# So minimum should be ~60px to accommodate padding + 2 lines
header_height = 60 if any(1 for section,
_ in all_rows if section == "header") else 0
# Check if any body rows contain images - if so, use larger height
body_height = 30
body_height = 60 # Increased from 30 to allow for text wrapping
for section, row in all_rows:
if section == "body":
for cell in row.cells():
@@ -468,7 +492,7 @@ class TableRenderer(Box):
body_height = max(body_height, 120)
break
footer_height = 30 if any(1 for section,
footer_height = 60 if any(1 for section,
_ in all_rows if section == "footer") else 0
row_heights = {