diff --git a/src/textual_webterm/svg_exporter.py b/src/textual_webterm/svg_exporter.py index 80d9527..0d5353b 100644 --- a/src/textual_webterm/svg_exporter.py +++ b/src/textual_webterm/svg_exporter.py @@ -173,9 +173,38 @@ def render_terminal_svg( continue # Start text element for this row - parts.append(f'') + # First collect all background rects, then the text element + row_bg_rects: list[str] = [] x = 10.0 # Starting x position with padding + for span in spans: + text = span["text"] + columns = span["columns"] + + # Background needs a separate rect (collected before text) + if span["has_bg"] and span["bg"] != background: + bg_width = columns * char_width + bg_y = y - font_size + 2 + row_bg_rects.append( + f'' + ) + + if not text or (text.isspace() and not span["has_bg"]): + # Skip empty spans without background, but advance position + x += columns * char_width + continue + + x += columns * char_width + + # Add background rects first + parts.extend(row_bg_rects) + + # Now add the text element + parts.append(f'') + + x = 10.0 # Reset x position for text rendering for span in spans: text = span["text"] columns = span["columns"] @@ -202,17 +231,6 @@ def render_terminal_svg( if classes: attrs.append(f'class="{" ".join(classes)}"') - # Background needs a separate rect - if span["has_bg"] and span["bg"] != background: - bg_width = columns * char_width - bg_y = y - font_size + 2 - parts.insert( - -1, # Insert before current text element - f'', - ) - parts.append(f'{_escape_xml(text)}') x += columns * char_width