Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 44 additions & 16 deletions src/textual/_markup_playground.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,21 @@
from textual.app import App, ComposeResult
from textual.content import Content
from textual.reactive import reactive
from textual.widgets import Static, TextArea
from textual.widgets import Footer, Pretty, Static, TextArea


class MarkupPlayground(App):

TITLE = "Markup Playground"
CSS = """
Screen {
& > * {
margin: 0 1;
height: 1fr;
}
Screen {
layout: vertical;
#editor {
width: 2fr;
width: 1fr;
height: 1fr;
border: tab $foreground 50%;
padding: 1;
margin: 1 1 0 0;
margin: 1 0 0 0;
&:focus {
border: tab $primary;
}
Expand All @@ -48,28 +44,57 @@ class MarkupPlayground(App):
}
overflow-y: auto;
}
#results {

#results {
padding: 1 1;
width: 1fr;
}
#spans-container {
border: tab $success;
overflow-y: auto;
margin: 0 0 0 1;
}
#spans {
padding: 1 1;
width: 1fr;
}
HorizontalGroup {
height: 1fr;
}
}
"""
AUTO_FOCUS = "#editor"

BINDINGS = [
("f1", "toggle('show_variables')", "Variables"),
("f2", "toggle('show_spans')", "Spans"),
]
variables: reactive[dict[str, object]] = reactive({})

show_variables = reactive(False)
show_spans = reactive(False)

def compose(self) -> ComposeResult:
with containers.HorizontalGroup():
yield (editor := TextArea(id="editor"))
yield (variables := TextArea("", id="variables", language="json"))
editor.border_title = "Markup"
variables.border_title = "Variables (JSON)"

with containers.VerticalScroll(
id="results-container", can_focus=False
) as container:
yield Static(id="results")
container.border_title = "Output"
with containers.HorizontalGroup():
with containers.VerticalScroll(id="results-container") as container:
yield Static(id="results")
container.border_title = "Output"
with containers.VerticalScroll(id="spans-container") as container:
yield Pretty([], id="spans")
container.border_title = "Spans"

yield Footer()

def watch_show_variables(self, show_variables: bool) -> None:
self.query_one("#variables").display = show_variables

def watch_show_spans(self, show_spans: bool) -> None:
self.query_one("#spans-container").display = show_spans

@on(TextArea.Changed, "#editor")
def on_markup_changed(self, event: TextArea.Changed) -> None:
Expand All @@ -78,13 +103,16 @@ def on_markup_changed(self, event: TextArea.Changed) -> None:
def update_markup(self) -> None:
results = self.query_one("#results", Static)
editor = self.query_one("#editor", TextArea)
spans = self.query_one("#spans", Pretty)
try:
content = Content.from_markup(editor.text, **self.variables)
results.update(content)
except Exception as error:
spans.update(content.spans)
except Exception:
from rich.traceback import Traceback

results.update(Traceback())
spans.update([])

self.query_one("#results-container").add_class("-error").scroll_end(
animate=False
Expand Down
11 changes: 5 additions & 6 deletions src/textual/markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,13 @@ def process_text(template_text: str, /) -> str:

content_text = "".join(text)
text_length = len(content_text)
while style_stack:
position, tag_body, _ = style_stack.pop()
for position, tag_body, _ in style_stack:
spans.append(Span(position, text_length, tag_body))

if style:
content = Content(content_text, [Span(0, len(content_text), style), *spans])
else:
content = Content(content_text, spans)
content = Content(
content_text,
[Span(0, len(content_text), style), *spans] if style else spans,
)

return content

Expand Down
7 changes: 7 additions & 0 deletions tests/test_markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@
],
),
),
(
"[#ff0000]Hello, [#ffffff]world!\nMy work here is done.",
Content(
"Hello, world!\nMy work here is done.",
spans=[Span(0, 35, style="#ff0000"), Span(7, 35, style="#ffffff")],
),
),
],
)
def test_to_content(markup: str, content: Content):
Expand Down
Loading