diff --git a/CHANGELOG.md b/CHANGELOG.md index 89843c0ae..8e74f4b2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Markdown table rendering issue with inline styles and links https://github.com/Textualize/rich/issues/3115 + ## [13.5.2] - 2023-08-01 ### Fixed diff --git a/rich/markdown.py b/rich/markdown.py index 704da3010..86edbfebd 100644 --- a/rich/markdown.py +++ b/rich/markdown.py @@ -314,7 +314,7 @@ class TableDataElement(MarkdownElement): @classmethod def create(cls, markdown: "Markdown", token: Token) -> "MarkdownElement": - style = str(token.attrs.get("style" "")) or "" + style = str(token.attrs.get("style")) or "" justify: JustifyMethod if "text-align:right" in style: @@ -330,15 +330,13 @@ def create(cls, markdown: "Markdown", token: Token) -> "MarkdownElement": return cls(justify=justify) def __init__(self, justify: JustifyMethod) -> None: - self.content: TextType = "" + self.content: Text = Text("", justify=justify) self.justify = justify def on_text(self, context: "MarkdownContext", text: TextType) -> None: - plain = text.plain if isinstance(text, Text) else text - style = text.style if isinstance(text, Text) else "" - self.content = Text( - plain, justify=self.justify, style=context.style_stack.current - ) + text = Text(text) if isinstance(text, str) else text + text.stylize(context.current_style) + self.content.append_text(text) class ListElement(MarkdownElement): diff --git a/tests/test_markdown.py b/tests/test_markdown.py index 1321dceab..08c81736e 100644 --- a/tests/test_markdown.py +++ b/tests/test_markdown.py @@ -121,7 +121,7 @@ def test_markdown_table(): """\ | Year | Title | Director | Box Office (USD) | |------|:------------------------------------------------:|:------------------|------------------:| -| 1982 | *E.T. the Extra-Terrestrial* | Steven Spielberg | $792.9 million | +| 1982 | *E.T. the Extra-Terrestrial* | Steven Spielberg | $792.9 million | | 1980 | Star Wars: Episode V – The Empire Strikes Back | Irvin Kershner | $538.4 million | | 1983 | Star Wars: Episode VI – Return of the Jedi | Richard Marquand | $475.1 million | | 1981 | Raiders of the Lost Ark | Steven Spielberg | $389.9 million | @@ -129,7 +129,40 @@ def test_markdown_table(): """ ) result = render(markdown) - expected = "\n \n \x1b[1m \x1b[0m\x1b[1mYear\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m Title \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mDirector \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mBox Office (USD)\x1b[0m\x1b[1m \x1b[0m \n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n 1982 \x1b[3m E.T. the Extra-Terrestrial \x1b[0m Steven Spielberg $792.9 million \n 1980 Star Wars: Episode V – The Empire Strikes Back Irvin Kershner $538.4 million \n 1983 Star Wars: Episode VI – Return of the Jedi Richard Marquand $475.1 million \n 1981 Raiders of the Lost Ark Steven Spielberg $389.9 million \n 1984 Indiana Jones and the Temple of Doom Steven Spielberg $333.1 million \n \n" + expected = "\n \n \x1b[1m \x1b[0m\x1b[1mYear\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m Title \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mDirector \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mBox Office (USD)\x1b[0m\x1b[1m \x1b[0m \n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n 1982 \x1b[3mE.T. the Extra-Terrestrial\x1b[0m Steven Spielberg $792.9 million \n 1980 Star Wars: Episode V – The Empire Strikes Back Irvin Kershner $538.4 million \n 1983 Star Wars: Episode VI – Return of the Jedi Richard Marquand $475.1 million \n 1981 Raiders of the Lost Ark Steven Spielberg $389.9 million \n 1984 Indiana Jones and the Temple of Doom Steven Spielberg $333.1 million \n \n" + assert result == expected + + +def test_inline_styles_in_table(): + """Regression test for https://github.com/Textualize/rich/issues/3115""" + markdown = Markdown( + """\ +| Year | This **column** displays _the_ movie _title_ ~~description~~ | Director | Box Office (USD) | +|------|:----------------------------------------------------------:|:------------------|------------------:| +| 1982 | *E.T. the Extra-Terrestrial* ([Wikipedia article](https://en.wikipedia.org/wiki/E.T._the_Extra-Terrestrial)) | Steven Spielberg | $792.9 million | +| 1980 | Star Wars: Episode V – The *Empire* **Strikes** ~~Back~~ | Irvin Kershner | $538.4 million | +""" + ) + result = render(markdown) + expected = "\n \n \x1b[1m \x1b[0m\x1b[1mYear\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mThis \x1b[0m\x1b[1mcolumn\x1b[0m\x1b[1m displays \x1b[0m\x1b[1;3mthe\x1b[0m\x1b[1m movie \x1b[0m\x1b[1;3mtitle\x1b[0m\x1b[1m \x1b[0m\x1b[1;9mdescription\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mDirector \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1mBox Office (USD)\x1b[0m\x1b[1m \x1b[0m \n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n 1982 \x1b[3mE.T. the Extra-Terrestrial\x1b[0m (\x1b]8;id=0;foo\x1b\\\x1b[4;34mWikipedia article\x1b[0m\x1b]8;;\x1b\\) Steven Spielberg $792.9 million \n 1980 Star Wars: Episode V – The \x1b[3mEmpire\x1b[0m \x1b[1mStrikes\x1b[0m \x1b[9mBack\x1b[0m Irvin Kershner $538.4 million \n \n" + assert result == expected + + +def test_inline_styles_with_justification(): + """Regression test for https://github.com/Textualize/rich/issues/3115 + + In particular, this tests the interaction between the change that was made to fix + #3115 and column text justification. + """ + markdown = Markdown( + """\ +| left | center | right | +| :- | :-: | -: | +| This is a long row | because it contains | a fairly long sentence. | +| a*b* _c_ ~~d~~ e | a*b* _c_ ~~d~~ e | a*b* _c_ ~~d~~ e |""" + ) + result = render(markdown) + expected = "\n \n \x1b[1m \x1b[0m\x1b[1mleft \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m center \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m right\x1b[0m\x1b[1m \x1b[0m \n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n This is a long row because it contains a fairly long sentence. \n a\x1b[3mb\x1b[0m \x1b[3mc\x1b[0m \x1b[9md\x1b[0m e a\x1b[3mb\x1b[0m \x1b[3mc\x1b[0m \x1b[9md\x1b[0m e a\x1b[3mb\x1b[0m \x1b[3mc\x1b[0m \x1b[9md\x1b[0m e \n \n" assert result == expected