-
-
Notifications
You must be signed in to change notification settings - Fork 992
Closed
Labels
Description
The Markdown Widget crashes if there is a closing rich tag in a heading. I.e., if there is a string like [/some_text]
in a markdown heading. This can become problematic when using Markdown extensions to WikiLinks and having something linke [[/test.md]]
in a heading.
Note in regular text this issue does not seem to be present. I have only seen this for headings.
Example
Running this
from textual.app import App, ComposeResult
from textual.widgets import MarkdownViewer
EXAMPLE_MARKDOWN = """\
# Markdown [/test]
"""
class MarkdownExampleApp(App):
def compose(self) -> ComposeResult:
yield MarkdownViewer(EXAMPLE_MARKDOWN, show_table_of_contents=True)
if __name__ == "__main__":
app = MarkdownExampleApp()
app.run()
will produce this error:
python3 markdown.py
╭──────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────────────────────────────────────────────────╮
│ /usr/local/lib/python3.11/site-packages/textual/widgets/_markdown.py:1056 in _on_markdown_table_of_contents_updated │
│ │
│ 1053 │ ) -> None: ╭────────────── locals ──────────────╮ │
│ 1054 │ │ self.query_one( │ message = TableOfContentsUpdated() │ │
│ 1055 │ │ │ MarkdownTableOfContents │ self = MarkdownViewer() │ │
│ ❱ 1056 │ │ ).table_of_contents = message.table_of_contents ╰────────────────────────────────────╯ │
│ 1057 │ │ message.stop() │
│ 1058 │ │
│ 1059 │ def _on_markdown_table_of_contents_selected( │
│ │
│ /usr/local/lib/python3.11/site-packages/textual/widgets/_markdown.py:920 in watch_table_of_contents │
│ │
│ 917 │ ╭──────────────────────── locals ─────────────────────────╮ │
│ 918 │ def watch_table_of_contents(self, table_of_contents: TableOfContentsType) -> None: │ self = MarkdownTableOfContents() │ │
│ 919 │ │ """Triggered when the table of contents changes.""" │ table_of_contents = [(1, 'Markdown [/test]', 'block1')] │ │
│ ❱ 920 │ │ self.set_table_of_contents(table_of_contents) ╰─────────────────────────────────────────────────────────╯ │
│ 921 │ │
│ 922 │ def set_table_of_contents(self, table_of_contents: TableOfContentsType) -> None: │
│ 923 │ │ """Set the table of contents. │
│ │
│ /usr/local/lib/python3.11/site-packages/textual/widgets/_markdown.py:940 in set_table_of_contents │
│ │
│ 937 │ │ │ │ │ node.allow_expand = True ╭──────────────────────── locals ─────────────────────────╮ │
│ 938 │ │ │ │ else: │ block_id = 'block1' │ │
│ 939 │ │ │ │ │ node = node.add(NUMERALS[level], expand=True) │ level = 1 │ │
│ ❱ 940 │ │ │ node.add_leaf(f"[dim]{NUMERALS[level]}[/] {name}", {"block_id": block_id}) │ name = 'Markdown [/test]' │ │
│ 941 │ │ node = TreeNode('TOC', None) │ │
│ 942 │ async def _on_tree_node_selected(self, message: Tree.NodeSelected) -> None: │ root = TreeNode('TOC', None) │ │
│ 943 │ │ node_data = message.node.data │ self = MarkdownTableOfContents() │ │
│ │ table_of_contents = [(1, 'Markdown [/test]', 'block1')] │ │
│ │ tree = Tree() │ │
│ ╰─────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.11/site-packages/textual/widgets/_tree.py:352 in add_leaf │
│ │
│ 349 │ │ Returns: ╭─────────────── locals ───────────────╮ │
│ 350 │ │ │ New node. │ data = {'block_id': 'block1'} │ │
│ 351 │ │ """ │ label = '[dim]Ⅰ[/] Markdown [/test]' │ │
│ ❱ 352 │ │ node = self.add(label, data, expand=False, allow_expand=False) │ self = TreeNode('TOC', None) │ │
│ 353 │ │ return node ╰──────────────────────────────────────╯ │
│ 354 │ │
│ 355 │ class RemoveRootError(Exception): │
│ │
│ /usr/local/lib/python3.11/site-packages/textual/widgets/_tree.py:331 in add │
│ │
│ 328 │ │ Returns: ╭────────────────── locals ───────────────────╮ │
│ 329 │ │ │ A new Tree node │ allow_expand = False │ │
│ 330 │ │ """ │ data = {'block_id': 'block1'} │ │
│ ❱ 331 │ │ text_label = self._tree.process_label(label) │ expand = False │ │
│ 332 │ │ node = self._tree._add_node(self, text_label, data) │ label = '[dim]Ⅰ[/] Markdown [/test]' │ │
│ 333 │ │ node._expanded = expand │ self = TreeNode('TOC', None) │ │
│ 334 │ │ node._allow_expand = allow_expand ╰─────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.11/site-packages/textual/widgets/_tree.py:635 in process_label │
│ │
│ 632 │ │ │ A Rich Text object. ╭─────────────── locals ───────────────╮ │
│ 633 │ │ """ │ label = '[dim]Ⅰ[/] Markdown [/test]' │ │
│ 634 │ │ if isinstance(label, str): │ self = Tree() │ │
│ ❱ 635 │ │ │ text_label = Text.from_markup(label) ╰──────────────────────────────────────╯ │
│ 636 │ │ else: │
│ 637 │ │ │ text_label = label │
│ 638 │ │ first_line = text_label.split()[0] │
│ │
│ /usr/local/lib/python3.11/site-packages/rich/text.py:286 in from_markup │
│ │
│ /usr/local/lib/python3.11/site-packages/rich/markup.py:167 in render │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
MarkupError: closing tag '[/test]' at position 19 doesn't match any open tag```