.. toc:: :min_level: 3
Markdown-2-Dash or M2D is a standalone package forked out of source code of official documentation of dash-mantine-components. Some form of M2D has always existed since the inception of the documentation, but I figured more people can make use of this to document their dash apps or component libraries.
Have a look here to see how this README would look after parsing with M2D. The render also works perfectly with dark mode without any extra code.
.. admonition::Note :icon: radix-icons:info-circled :color: red
The theme switcher has been added only for this demo, its not available as part of markdown2dash.
pip install markdown2dash
poetry add markdown2dash
.. admonition::Note :icon: radix-icons:info-circled :color: red
Latest dmc is based on REACT 18. You need to set REACT_VERSION=18.2.0 before starting the app.
Let's start by parsing the readme of this repository with M2D.
.. admonition::Note :icon: radix-icons:bookmark-filled :color: yellow
Make sure to include stylesheets for all extensions you are planning to use in your app.
import dash_mantine_components as dmc
from dash import Dash
from markdown2dash import parse
with open("../README.md") as f:
md = f.read()
layout = parse(md)
stylesheets = [
"https://unpkg.com/@mantine/dates@7/styles.css",
"https://unpkg.com/@mantine/code-highlight@7/styles.css",
"https://unpkg.com/@mantine/charts@7/styles.css",
"https://unpkg.com/@mantine/carousel@7/styles.css",
"https://unpkg.com/@mantine/notifications@7/styles.css",
"https://unpkg.com/@mantine/nprogress@7/styles.css",
]
app = Dash(__name__, external_stylesheets=stylesheets)
app.layout = dmc.MantineProvider(
dmc.Container(layout, size="lg", p=20),
theme={
"primaryColor": "indigo",
"colorScheme": "light",
"fontFamily": "'Inter', sans-serif",
"components": {
"Table": {"defaultProps": {"striped": True, "withTableBorder": True, "highlightOnHover": True}},
"Alert": {"styles": {"title": {"fontWeight": 500}}},
},
},
)
if __name__ == "__main__":
app.run()
There's no styling by default, so you'll have to provide your own css. You can do that in two ways:
- Use MantineProvider to style your page (as you can see above)
- Create CSS files. You can get started with the one provided in this repository: styles.css
Each component rendered by M2D will have a class name attached to it.
M2D can render following types of tokens:
Token | Class Name |
---|---|
Links | .m2d-link |
Paragraph | .m2d-paragraph |
Emphasis | .m2d-emphasis |
Strong | .m2d-strong |
Code Span | .m2d-codespan |
Heading | .m2d-heading |
Thematic Break | .m2d-thematic-break |
Block Code | .m2d-block-code |
Block Quote | .m2d-block-quote |
List Item | .m2d-list-item |
List | .m2d-list |
Strikethrough | .m2d-strikethrough |
Mark | .m2d-mark |
Table | .m2d-table |
Table Head | .m2d-table-head |
Table Body | .m2d-table-body |
Table Row | .m2d-table-row |
Table Cell | .m2d-table-cell |
Spoiler | .m2d-block-spoiler |
Admonition | .m2d-block-admonition |
Divider | .m2d-block-divider |
Executable Block | .m2d-block-exec |
Image | .m2d-block-image |
Dash Component Docs | .m2d-block-kwargs |
Source Code | .m2d-block-source |
Table of Contents | .m2d-block-toc |
M2D includes some special directives enabling you to do a lot more than just rendering static markdown into a dash layout.
The directives are all extensible, and you can just overwrite the render method to suit your own needs. The default render method is provided in all directives out of the box.
You can use the exec
directive to embed the output of a python script as well as its source code. This directive expects that
you have stored the output layout in the variable called component
.
.. exec::example.navlink
Here's the output if you are viewing this in a dash app:
.. exec::example.navlink
You can hide the source code using the code
argument, and the border using border
.
.. exec::example.navlink
:code: false
:border: false
You can use SourceCode directive to display code from a file in your project. The path of file is relative to current working directory.
Here's the css used to style this page.
.. source::example/assets/styles.css
:language: css
.. source::example/assets/styles.css :language: css
You can use admonition
directive to add dmc.Alert components in your page.
Admonition directive uses DashIconify to render icons as well.
.. admonition::Alert Title
:icon: radix-icons:github-logo
:variant: outline
This is to show that now you can render alerts directly from the markdown.
Here's the output if you are viewing this in a dash app:
.. admonition::Alert Title :icon: radix-icons:github-logo :variant: outline
This is to show that now you can render alerts directly from the markdown.
Render images using dmc.Image like this:
.. image::https://www.dash-mantine-components.com/assets/superman.jpeg
:w: 300px
:h: 300px
Here's the output if you are viewing this in a dash app:
.. image::https://www.dash-mantine-components.com/assets/superman.jpeg :w: 300px :h: 300px
It's very simple to add API docs of your component using M2D. You just have to specify the package and the component. Let's create one for DashIconify:
.. kwargs::DashIconify
:library: dash_iconify
Here's the output if you are viewing this in a dash app:
.. kwargs::DashIconify :library: dash_iconify
This directive will parse all the headings and create a table of contents like this:
# a placeholder for self and a list of [<level>, <title>, <id>]
[
(4, 'Installation', 'installation'),
(4, 'Quickstart', 'quickstart'),
(5, 'Example App', 'example-app'),
(4, 'Special Directives', 'special-directives'),
(5, 'Dash Component API Docs', 'dash-component-api-docs'),
(5, 'Table of Contents', 'table-of-contents')
]
This will then be used to render the TOC using the render method. You can enable TOC like this:
.. toc::
:min_level: 3
A simple way to add dividers would be to just add ---
in your markdown file.
---
But let's say you to add a label to the divider and also customize it. You can use the divider directive to do that.
.. divider::Section Changed!
:labelPosition: left
.. divider::Section Changed!
.. divider::Section Changed!
:labelPosition: right
.. divider::Section Changed! :labelPosition: left
.. divider::Section Changed!
.. divider::Section Changed! :labelPosition: right
You can create tasks list like below and a checkbox list will be rendered automatically in your dash app.
- [ ] Create README for library.
- [x] Resolve GitHub issues [here](https://github.com/snehilvj/dash-mantine-components).
- Create README for library.
- Resolve GitHub issues here.
Create spoiler content like this:
>! In the final moments of Dune: Part Two...
>! Why does Paul need to marry Princess Irulan...
>! In the book, we learn that a dea...
And this is how it will look when rendered (wrapped by dmc.Spoiler):
! In the final moments of Dune: Part Two, Paul Atreides does two shocking things: he says he’ll marry Princess Irulan (Florence Pugh), and then, he sends his Fremen troops out into the universe to start a holy war against the great houses. This is the horrific future vision that Paul has been seeing since Dune: Part One. The Fremen and House Atreides prevail on Arrakis, but the cost is a massive war that will burn half the universe. Let's break down how this happens. ! Why does Paul need to marry Princess Irulan to take over the throne from Emperor Shaddam IV? Because he has control of the spice on Arrakis, couldn’t he just kill everyone and marry Chani, his true love? The answer lies in the book. When Paul sees Irulan in the final pages of the book, he thinks, “There’s my key,” and on the very last page of the book, he tells Chani, “We must obey the forms.” This means that he wants to gain power within the system. ! In the book, we learn that a deal has been made to “place a Bene Gesserit on the throne, and Irulan is the one they’ve groomed for it.” In the movie, before everything goes down in the end, Reverend Mother Gaius Helen Mohiam tells Irulan that “there’s one way your family can remain in power… are you prepared?”
Let's try to render a mix of items in a nested list.
1. Ingredients
- spaghetti
- marinara sauce
- salt
2. Cooking
1. Bring water to boil, add a pinch of salt and spaghetti.
2. Cook until pasta is **tender**.
3. Serve: Drain the pasta on a plate. Add heated sauce.
4. No man is lonely eating spaghetti, it requires so much attention.
- Ingredients
- spaghetti
- marinara sauce
- salt
- Cooking
- Bring water to boil, add a pinch of salt and spaghetti.
- Cook until pasta is tender.
- Serve: Drain the pasta on a plate. Add heated sauce.
- No man is lonely eating spaghetti, it requires so much attention.
You can use the exec block to add charts in your app. The following block will render a BarChart as defined in example/chart.py
.. exec::example.chart
:code: false
:border: true
.. exec::example.chart :code: false :border: false
Life is like npm install – you never know what you are going to get.
You can create a new directive by extending the BaseDirective class and creating a new parser. Here's how you can add a new directive that adds a scroll to top button in the bottom right of your app.
.. source::example/scroll.py
The associated css class name will be: m2d-block-scroll
.
Create a new parser using your new directive like below:
from markdown2dash import create_parser, DEFAULT_DIRECTIVES
parse = create_parser(DEFAULT_DIRECTIVES + [ScrollToTop()])
layout = parse(content)
And here's how you can use it in the markdown.
.. scroll::
.. scroll::
.. exec::example.theme :code: false :border: false