diff --git a/CHANGELOG.md b/CHANGELOG.md index 041c7ff433..af50714fbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fixed running `App.run` after `asyncio.run` https://github.com/Textualize/textual/pull/5799 - Fixed triggering a deprecation warning in py >= 3.10 https://github.com/Textualize/textual/pull/5799 - Fixed `Input` invalid cursor position after updating the value https://github.com/Textualize/textual/issues/5811 +- Fixed issue where nested colors in markup were ignored https://github.com/Textualize/textual/issues/5826 ### Added - Exposed `CollapsibleTitle` https://github.com/Textualize/textual/pull/5810 - -### Added - - Added `Color.hsv` property and `Color.from_hsv` class method https://github.com/Textualize/textual/pull/5803 ## [3.2.0] - 2025-05-02 diff --git a/src/textual/markup.py b/src/textual/markup.py index 06a0effd98..a0684e0396 100644 --- a/src/textual/markup.py +++ b/src/textual/markup.py @@ -5,6 +5,8 @@ from __future__ import annotations +from operator import attrgetter + from textual.css.parse import substitute_references from textual.css.tokenizer import UnexpectedEnd @@ -411,9 +413,12 @@ def process_text(template_text: str, /) -> str: content_text = "".join(text) text_length = len(content_text) - for position, tag_body, _ in style_stack: + while style_stack: + position, tag_body, _ = style_stack.pop() spans.append(Span(position, text_length, tag_body)) + spans = sorted(spans[::-1], key=attrgetter("start")) + content = Content( content_text, [Span(0, len(content_text), style), *spans] if style else spans, diff --git a/tests/test_markup.py b/tests/test_markup.py index 718c61752c..46d7101994 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -35,9 +35,9 @@ Content( "What is up with you?", spans=[ + Span(0, 20, style="b"), Span(0, 10, style="on red"), Span(5, 20, style="i"), - Span(0, 20, style="b"), ], ), ), @@ -84,6 +84,17 @@ spans=[Span(0, 35, style="#ff0000"), Span(7, 35, style="#ffffff")], ), ), + ( + "[blue][green][red]R[/red]G[/green]B[/blue]", + Content( + "RGB", + spans=[ + Span(0, 3, style="blue"), + Span(0, 2, style="green"), + Span(0, 1, style="red"), + ], + ), + ), ], ) def test_to_content(markup: str, content: Content):