From 71325bb5bbb194ae0c09256c3035187354e042c2 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 10 Feb 2022 14:31:37 +0000 Subject: [PATCH] Fix issue with markup escaping --- rich/markup.py | 15 ++++++++------- tests/test_markup.py | 8 ++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/rich/markup.py b/rich/markup.py index 58903f6b..c7c587cf 100644 --- a/rich/markup.py +++ b/rich/markup.py @@ -1,21 +1,20 @@ +import re from ast import literal_eval from operator import attrgetter -import re from typing import Callable, Iterable, List, Match, NamedTuple, Optional, Tuple, Union +from ._emoji_replace import _emoji_replace +from .emoji import EmojiVariant from .errors import MarkupError from .style import Style from .text import Span, Text -from .emoji import EmojiVariant -from ._emoji_replace import _emoji_replace - RE_TAGS = re.compile( - r"""((\\*)\[([a-z#\/@].*?)\])""", + r"""((\\*)\[([a-z#/@][^[]*?)])""", re.VERBOSE, ) -RE_HANDLER = re.compile(r"^([\w\.]*?)(\(.*?\))?$") +RE_HANDLER = re.compile(r"^([\w.]*?)(\(.*?\))?$") class Tag(NamedTuple): @@ -146,6 +145,8 @@ def render( for position, plain_text, tag in _parse(markup): if plain_text is not None: + # Capture open brace escapes, where the brace is not part of a tag. + plain_text = plain_text.replace("\\[", "[") append(emoji_replace(plain_text) if emoji else plain_text) elif tag is not None: if tag.name.startswith("/"): # Closing tag @@ -233,8 +234,8 @@ if __name__ == "__main__": # pragma: no cover ":warning-emoji: [bold red blink] DANGER![/]", ] - from rich.table import Table from rich import print + from rich.table import Table grid = Table("Markup", "Result", padding=(0, 1)) diff --git a/tests/test_markup.py b/tests/test_markup.py index 5a0acbbf..106738bd 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -1,7 +1,7 @@ import pytest from rich.console import Console -from rich.markup import escape, MarkupError, _parse, render, Tag, RE_TAGS +from rich.markup import RE_TAGS, MarkupError, Tag, _parse, escape, render from rich.text import Span @@ -139,6 +139,11 @@ def test_markup_error(): assert render("[foo]hello[/bar]") +def test_markup_escape(): + result = str(render("[dim white]\[url=[/]")) + assert result == "[url=" + + def test_escape_escape(): # Escaped escapes (i.e. double backslash)should be treated as literal result = render(r"\\[bold]FOO") @@ -165,7 +170,6 @@ def test_escape_escape(): def test_events(): - result = render("[@click]Hello[/@click] [@click='view.toggle', 'left']World[/]") assert str(result) == "Hello World"