From 0e13088b1174e6bb4f9c509de0493bcbc3480b63 Mon Sep 17 00:00:00 2001 From: Gareth Davidson Date: Thu, 10 Jul 2025 09:26:09 +0100 Subject: [PATCH] Ensure ansi colors have triplets during conversion closes #5946 --- src/textual/filter.py | 8 ++++++++ tests/test_ansi_truecolor_filter.py | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/test_ansi_truecolor_filter.py diff --git a/src/textual/filter.py b/src/textual/filter.py index 5a2984f381..035461f9fd 100644 --- a/src/textual/filter.py +++ b/src/textual/filter.py @@ -252,6 +252,14 @@ def truecolor_style(self, style: Style, background: RichColor) -> Style: ) # Convert dim style to RGB if style.dim and color is not None: + if color.triplet is None: + color = RichColor.from_rgb( + *color.get_truecolor(terminal_theme, foreground=True) + ) + if background.triplet is None: + background = RichColor.from_rgb( + *background.get_truecolor(terminal_theme, foreground=False) + ) color = dim_color(background, color) style += NO_DIM diff --git a/tests/test_ansi_truecolor_filter.py b/tests/test_ansi_truecolor_filter.py new file mode 100644 index 0000000000..6a08370264 --- /dev/null +++ b/tests/test_ansi_truecolor_filter.py @@ -0,0 +1,25 @@ +from rich.color import Color as RichColor +from rich.color import ColorType +from rich.segment import Segment +from rich.style import Style +from rich.terminal_theme import MONOKAI + +from textual.color import Color +from textual.filter import ANSIToTruecolor + + +def test_ansi_to_truecolor_8_bit_dim(): + """Test that converting an 8-bit color with dim doesn't crash.""" + # Given + ansi_filter = ANSIToTruecolor(MONOKAI) + test_color = RichColor("color(253)", ColorType.EIGHT_BIT, number=253) + test_style = Style(color=test_color, dim=True) + segments = [Segment("This should not crash", style=test_style)] + background_color = Color(0, 0, 0) + + # When + # This line will crash if the bug is present + new_segments = ansi_filter.apply(segments, background_color) + + # Then + assert new_segments is not None