Skip to content

MarkdownViewer

Added in version 0.11.0

A Widget to display Markdown content with an optional Table of Contents.

  • Focusable
  • Container

Note

This Widget adds browser-like functionality on top of the Markdown widget.

Example

The following example displays Markdown from a string and a Table of Contents.

MarkdownExampleApp ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▼ Ⅰ Markdown Viewer ├── Ⅱ FeaturesMarkdown Viewer ├── Ⅱ Tables └── Ⅱ Code Blocks▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ This is an example of Textual's MarkdownViewer widget. ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁                            Features                            ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Markdown syntax and extensions are supported. ● Typography emphasisstronginline code etc. ● Headers ● Lists (bullet and ordered) ● Syntax highlighted code blocks ● Tables! ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁                             Tables                             ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Tables are displayed in a DataTable widget. ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ Name          TypeDefaultDescription                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  show_headerboolTrueShow the table header              fixed_rowsint0Number of fixed rows               fixed_columnsint0Number of fixed columns            zebra_stripesboolFalseDisplay alternating colors on rows header_heightint1Height of header row               show_cursorboolTrueShow a cell cursor                 ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

from textual.app import App, ComposeResult
from textual.widgets import MarkdownViewer

EXAMPLE_MARKDOWN = """\
# Markdown Viewer

This is an example of Textual's `MarkdownViewer` widget.


## Features

Markdown syntax and extensions are supported.

- Typography *emphasis*, **strong**, `inline code` etc.
- Headers
- Lists (bullet and ordered)
- Syntax highlighted code blocks
- Tables!

## Tables

Tables are displayed in a DataTable widget.

| Name            | Type   | Default | Description                        |
| --------------- | ------ | ------- | ---------------------------------- |
| `show_header`   | `bool` | `True`  | Show the table header              |
| `fixed_rows`    | `int`  | `0`     | Number of fixed rows               |
| `fixed_columns` | `int`  | `0`     | Number of fixed columns            |
| `zebra_stripes` | `bool` | `False` | Display alternating colors on rows |
| `header_height` | `int`  | `1`     | Height of header row               |
| `show_cursor`   | `bool` | `True`  | Show a cell cursor                 |


## Code Blocks

Code blocks are syntax highlighted, with guidelines.

```python
class ListViewExample(App):
    def compose(self) -> ComposeResult:
        yield ListView(
            ListItem(Label("One")),
            ListItem(Label("Two")),
            ListItem(Label("Three")),
        )
        yield Footer()
```
"""


class MarkdownExampleApp(App):
    def compose(self) -> ComposeResult:
        yield MarkdownViewer(EXAMPLE_MARKDOWN, show_table_of_contents=True)


if __name__ == "__main__":
    app = MarkdownExampleApp()
    app.run()

Reactive Attributes

Name Type Default Description
show_table_of_contents bool True Wether a Table of Contents should be displayed with the Markdown.

Messages

This widget posts no messages.

Bindings

This widget has no bindings.

Component Classes

This widget has no component classes.

See Also


textual.widgets.MarkdownViewer class

def __init__(
    self,
    markdown=None,
    *,
    show_table_of_contents=True,
    name=None,
    id=None,
    classes=None,
    parser_factory=None
):

Bases: VerticalScroll

A Markdown viewer widget.

Parameters
Parameter Default Description
markdown
str | None
None

String containing Markdown, or None to leave blank.

show_table_of_contents
bool
True

Show a table of contents in a sidebar.

name
str | None
None

The name of the widget.

id
str | None
None

The ID of the widget in the DOM.

classes
str | None
None

The CSS classes of the widget.

parser_factory
Callable[[], MarkdownIt] | None
None

A factory function to return a configured MarkdownIt instance. If None, a "gfm-like" parser is used.

document property

document: Markdown

The Markdown document widget.

table_of_contents property

table_of_contents: MarkdownTableOfContents

The table of contents widget.

back async

def back(self):

Go back one level in the history.

forward async

def forward(self):

Go forward one level in the history.

go async

def go(self, location):

Navigate to a new document path.

textual.widgets.markdown

TableOfContentsType module-attribute

TableOfContentsType: TypeAlias = (
    "list[tuple[int, str, str | None]]"
)

Information about the table of contents of a markdown document.

The triples encode the level, the label, and the optional block id of each heading.

Markdown class

def __init__(
    self,
    markdown=None,
    *,
    name=None,
    id=None,
    classes=None,
    parser_factory=None
):

Bases: Widget

Parameters
Parameter Default Description
markdown
str | None
None

String containing Markdown or None to leave blank for now.

name
str | None
None

The name of the widget.

id
str | None
None

The ID of the widget in the DOM.

classes
str | None
None

The CSS classes of the widget.

parser_factory
Callable[[], MarkdownIt] | None
None

A factory function to return a configured MarkdownIt instance. If None, a "gfm-like" parser is used.

COMPONENT_CLASSES class-attribute instance-attribute

COMPONENT_CLASSES = {'em', 'strong', 's', 'code_inline'}

These component classes target standard inline markdown styles. Changing these will potentially break the standard markdown formatting.

Class Description
code_inline Target text that is styled as inline code.
em Target text that is emphasized inline.
s Target text that is styled inline with strykethrough.
strong Target text that is styled inline with strong.

code_dark_theme class-attribute instance-attribute

code_dark_theme: reactive[str] = reactive('material')

The theme to use for code blocks when in dark mode.

code_light_theme class-attribute instance-attribute

code_light_theme: reactive[str] = reactive("material-light")

The theme to use for code blocks when in light mode.

LinkClicked class

def __init__(self, markdown, href):

Bases: Message

A link in the document was clicked.

control property
control: Markdown

The Markdown widget containing the link clicked.

This is an alias for LinkClicked.markdown and is used by the on decorator.

href instance-attribute
href: str = href

The link that was selected.

markdown instance-attribute
markdown: Markdown = markdown

The Markdown widget containing the link clicked.

TableOfContentsSelected class

def __init__(self, markdown, block_id):

Bases: Message

An item in the TOC was selected.

block_id instance-attribute
block_id: str = block_id

ID of the block that was selected.

control property
control: Markdown

The Markdown widget where the selected item is.

This is an alias for TableOfContentsSelected.markdown and is used by the on decorator.

markdown instance-attribute
markdown: Markdown = markdown

The Markdown widget where the selected item is.

TableOfContentsUpdated class

def __init__(self, markdown, table_of_contents):

Bases: Message

The table of contents was updated.

control property
control: Markdown

The Markdown widget associated with the table of contents.

This is an alias for TableOfContentsUpdated.markdown and is used by the on decorator.

markdown instance-attribute
markdown: Markdown = markdown

The Markdown widget associated with the table of contents.

table_of_contents instance-attribute
table_of_contents: TableOfContentsType = table_of_contents

Table of contents.

goto_anchor method

def goto_anchor(self, anchor):

Try and find the given anchor in the current document.

Parameters
Parameter Default Description
anchor
str
required

The anchor to try and find.

Note

The anchor is found by looking at all of the headings in the document and finding the first one whose slug matches the anchor.

Note that the slugging method used is similar to that found on GitHub.

Returns
Type Description
bool

True when the anchor was found in the current document, False otherwise.

load async

def load(self, path):

Load a new Markdown document.

Parameters
Parameter Default Description
path
Path
required

Path to the document.

Raises
Type Description
OSError

If there was some form of error loading the document.

Note

The exceptions that can be raised by this method are all of those that can be raised by calling Path.read_text.

sanitize_location staticmethod

def sanitize_location(location):

Given a location, break out the path and any anchor.

Parameters
Parameter Default Description
location
str
required

The location to sanitize.

Returns
Type Description
Path

A tuple of the path to the location cleaned of any anchor, plus

str

the anchor (or an empty string if none was found).

unhandled_token method

def unhandled_token(self, token):

Process an unhandled token.

Parameters
Parameter Default Description
token
Token
required

The MarkdownIt token to handle.

Returns
Type Description
MarkdownBlock | None

Either a widget to be added to the output, or None.

update method

def update(self, markdown):

Update the document with new Markdown.

Parameters
Parameter Default Description
markdown
str
required

A string containing Markdown.

Returns
Type Description
AwaitComplete

An optionally awaitable object. Await this to ensure that all children have been mounted.

MarkdownBlock class

def __init__(self, markdown, *args, **kwargs):

Bases: Static

The base class for a Markdown Element.

def action_link(self, href):

Called on link click.

build_from_token method

def build_from_token(self, token):

Build the block content from its source token.

This method allows the block to be rebuilt on demand, which is useful when the styles assigned to the Markdown.COMPONENT_CLASSES change.

See https://github.com/Textualize/textual/issues/3464 for more information.

Parameters
Parameter Default Description
token
Token
required

The token from which this block is built.

notify_style_update method

def notify_style_update(self):

If CSS was reloaded, try to rebuild this block from its token.

rebuild method

def rebuild(self):

Rebuild the content of the block if we have a source token.

MarkdownTableOfContents class

def __init__(
    self,
    markdown,
    name=None,
    id=None,
    classes=None,
    disabled=False,
):

Bases: Widget

Displays a table of contents for a markdown document.

Parameters
Parameter Default Description
markdown
Markdown
required

The Markdown document associated with this table of contents.

name
str | None
None

The name of the widget.

id
str | None
None

The ID of the widget in the DOM.

classes
str | None
None

The CSS classes for the widget.

disabled
bool
False

Whether the widget is disabled or not.

markdown instance-attribute

markdown: Markdown = markdown

The Markdown document associated with this table of contents.

table_of_contents class-attribute instance-attribute

table_of_contents = reactive[Optional[TableOfContentsType]](
    None, init=False
)

Underlying data to populate the table of contents widget.

rebuild_table_of_contents method

def rebuild_table_of_contents(self, table_of_contents):

Rebuilds the tree representation of the table of contents data.

Parameters
Parameter Default Description
table_of_contents
TableOfContentsType
required

Table of contents.

watch_table_of_contents method

def watch_table_of_contents(self, table_of_contents):

Triggered when the table of contents changes.