Skip to content

Commit d999c69

Browse files
authored
Allow customizing the markdown parser (#2075)
* Allow customizing the markdown parser For instance, code using Markdown might wish to create a markdown parser that does not parse embedded HTML: ```py def parser_factory(): parser = MarkdownIt("gfm-like") parser.options["html"] = False return parser ``` * blacken * Implement requested changes * fix AttributeError
1 parent f5e779c commit d999c69

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10+
### Added
11+
- Added `parser_factory` argument to `Markdown` and `MarkdownViewer` constructors https://github.com/Textualize/textual/pull/2075
12+
1013
### Changed
1114

1215
- Dropped "loading-indicator--dot" component style from LoadingIndicator https://github.com/Textualize/textual/pull/2050

src/textual/widgets/_markdown.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from pathlib import Path, PurePath
4-
from typing import Iterable
4+
from typing import Iterable, Callable
55

66
from markdown_it import MarkdownIt
77
from rich import box
@@ -541,6 +541,7 @@ def __init__(
541541
name: str | None = None,
542542
id: str | None = None,
543543
classes: str | None = None,
544+
parser_factory: Callable[[], MarkdownIt] | None = None,
544545
):
545546
"""A Markdown widget.
546547
@@ -549,9 +550,11 @@ def __init__(
549550
name: The name of the widget.
550551
id: The ID of the widget in the DOM.
551552
classes: The CSS classes of the widget.
553+
parser_factory: A factory function to return a configured MarkdownIt instance. If `None`, a "gfm-like" parser is used.
552554
"""
553555
super().__init__(name=name, id=id, classes=classes)
554556
self._markdown = markdown
557+
self._parser_factory = parser_factory
555558

556559
class TableOfContentsUpdated(Message, bubble=True):
557560
"""The table of contents was updated."""
@@ -606,7 +609,11 @@ async def update(self, markdown: str) -> None:
606609
"""
607610
output: list[MarkdownBlock] = []
608611
stack: list[MarkdownBlock] = []
609-
parser = MarkdownIt("gfm-like")
612+
parser = (
613+
MarkdownIt("gfm-like")
614+
if self._parser_factory is None
615+
else self._parser_factory()
616+
)
610617

611618
content = Text()
612619
block_id: int = 0
@@ -831,6 +838,7 @@ def __init__(
831838
name: str | None = None,
832839
id: str | None = None,
833840
classes: str | None = None,
841+
parser_factory: Callable[[], MarkdownIt] | None = None,
834842
):
835843
"""Create a Markdown Viewer object.
836844
@@ -840,10 +848,12 @@ def __init__(
840848
name: The name of the widget.
841849
id: The ID of the widget in the DOM.
842850
classes: The CSS classes of the widget.
851+
parser_factory: A factory function to return a configured MarkdownIt instance. If `None`, a "gfm-like" parser is used.
843852
"""
844853
super().__init__(name=name, id=id, classes=classes)
845854
self.show_table_of_contents = show_table_of_contents
846855
self._markdown = markdown
856+
self._parser_factory = parser_factory
847857

848858
@property
849859
def document(self) -> Markdown:
@@ -882,7 +892,7 @@ def watch_show_table_of_contents(self, show_table_of_contents: bool) -> None:
882892

883893
def compose(self) -> ComposeResult:
884894
yield MarkdownTableOfContents()
885-
yield Markdown()
895+
yield Markdown(parser_factory=self._parser_factory)
886896

887897
def on_markdown_table_of_contents_updated(
888898
self, message: Markdown.TableOfContentsUpdated

0 commit comments

Comments
 (0)