Skip to content

Commit ec32597

Browse files
committed
Fix for overlapping tags
1 parent 1d893a9 commit ec32597

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

src/textual/markup.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from __future__ import annotations
77

8+
from operator import attrgetter
9+
810
from textual.css.parse import substitute_references
911
from textual.css.tokenizer import UnexpectedEnd
1012

@@ -411,8 +413,14 @@ def process_text(template_text: str, /) -> str:
411413

412414
content_text = "".join(text)
413415
text_length = len(content_text)
414-
for position, tag_body, _ in style_stack:
415-
spans.append(Span(position, text_length, tag_body))
416+
spans.extend(
417+
[
418+
Span(position, text_length, tag_body)
419+
for position, tag_body, _ in reversed(style_stack)
420+
]
421+
)
422+
spans.reverse()
423+
spans.sort(key=attrgetter("start"))
416424

417425
content = Content(
418426
content_text,

tests/test_markup.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535
Content(
3636
"What is up with you?",
3737
spans=[
38+
Span(0, 20, style="b"),
3839
Span(0, 10, style="on red"),
3940
Span(5, 20, style="i"),
40-
Span(0, 20, style="b"),
4141
],
4242
),
4343
),
@@ -84,6 +84,58 @@
8484
spans=[Span(0, 35, style="#ff0000"), Span(7, 35, style="#ffffff")],
8585
),
8686
),
87+
(
88+
"[blue][green][red]R[/red]G[/green]B[/blue]",
89+
Content(
90+
"RGB",
91+
spans=[
92+
Span(0, 3, "blue"),
93+
Span(0, 2, "green"),
94+
Span(0, 1, "red"),
95+
],
96+
),
97+
),
98+
(
99+
"[red][blue]X[/blue][/red]",
100+
Content(
101+
"X",
102+
spans=[
103+
Span(0, 1, "red"),
104+
Span(0, 1, "blue"),
105+
],
106+
),
107+
),
108+
# Non-nested tags
109+
(
110+
"[red][blue]X[/red][/blue]",
111+
Content(
112+
"X",
113+
spans=[
114+
Span(0, 1, "blue"),
115+
Span(0, 1, "red"),
116+
],
117+
),
118+
),
119+
(
120+
"[red][blue]X[/red]",
121+
Content(
122+
"X",
123+
spans=[
124+
Span(0, 1, "blue"),
125+
Span(0, 1, "red"),
126+
],
127+
),
128+
),
129+
(
130+
"[red][blue]X",
131+
Content(
132+
"X",
133+
spans=[
134+
Span(0, 1, "red"),
135+
Span(0, 1, "blue"),
136+
],
137+
),
138+
),
87139
],
88140
)
89141
def test_to_content(markup: str, content: Content):

0 commit comments

Comments
 (0)