Markdown Toolkit¶
A python library for creating and manipulating markdown with an object oriented interface.
This library is split into two aims:
- Generation of markdown with python to create documents or fragments of documents.
-
Injection of static text, file contents, or dynamically generated markdown into existing documents.
-
Generation¶
This example reaches out to a public API, grabs a response and generates a document using those dynamic responses using the MarkdownDocument class.
examples/document_quickstart.pyfrom datetime import datetime import requests from markdown_toolkit import MarkdownDocument, bold, image QUOTES_COUNT = 10 def calculate_age() -> int: year = 365 * 24 * 60 * 60 rons_birthday = datetime(year=1967, month=4, day=30) now = datetime.now() return int(divmod((now - rons_birthday).total_seconds(), year)[0]) quotes = requests.get( f"http://ron-swanson-quotes.herokuapp.com/v2/quotes/{QUOTES_COUNT}" ) doc = MarkdownDocument() with doc.heading("Ron Swanson"): with doc.heading("Biography"): doc.paragraph(image(uri="img/ron_swanson.jpg")) doc.list(f'{bold("Name")}: Ronald Ulysses "Ron" Swanson') doc.list(f'{bold("Age")}: {calculate_age()}') with doc.heading(f"Top {QUOTES_COUNT} Greatest Quotes"): doc.paragraph( "Ron is known for some insightful quotes, here's some of the best:" ) for quote in quotes.json(): doc.list(quote) print(doc.render())
# Ron Swanson ## Biography ![img/ron_swanson.jpg](img/ron_swanson.jpg) * **Name**: Ronald Ulysses "Ron" Swanson * **Age**: 55 ## Top 10 Greatest Quotes Ron is known for some insightful quotes, here's some of the best: * I love riddles! * I believe luck is a concept invented by the weak to explain their failures. * When I'm done eating a Mulligan's meal, for weeks afterwards, there are flecks of meat in my mustache. And I refuse to clean it because every now and then a piece of meat will fall into my mouth. * If it doesn’t have meat, it’s a snack. * Veganism is the sad result of a morally corrupt mind. Reconsider your life. * Turkey can never beat cow. * I don't want to paint with a broad brush here, but every single contractor in the world is a miserable, incompetent thief. * History began July 4th, 1776. Anything before that was a mistake. * I like saying ‘No,’ it lowers their enthusiasm. * When I eat, it is the food that is scared.
Ron Swanson¶
Biography¶
- Name: Ronald Ulysses "Ron" Swanson
- Age: 55
Top 10 Greatest Quotes¶
Ron is known for some insightful quotes, here's some of the best:
- I believe luck is a concept invented by the weak to explain their failures.
- Once a year, every branch of this government meets in a room and announces what they intend to waste taxpayer money on.
- My first ex-wife’s name is Tammy. My second ex-wife’s name is Tammy. My Mom’s name is Tamara…she goes by Tammy.
- The less I know about other people's affairs, the happier I am. I'm not interested in caring about people. I once worked with a guy for three years and never learned his name. Best friend I ever had. We still never talk sometimes.
- I'll take that steak to go. Please and thank you.
- On nights like this when the cold winds blow, the air is awash in the swirling eddies of our dream, come with me and find safe haven in a warm bathtub full of my jazz.
- The whole point of this country is if you want to eat garbage, balloon up to 600 pounds and die of a heart attack at 43, you can! You are free to do so. To me, that’s beautiful.
- Keep your tears in your eyes where they belong.
- I leave no meat behind. It’s an honor thing.
- Please and thank you.
-
Injection¶
This example takes a source document and uses a script to inject dynamically generated table markdown from an external HTTP request using both the MarkdownDocument and MarkdownInjector classes.
examples/injection_quickstart.pyfrom typing import Generator import requests from markdown_toolkit import MarkdownDocument, MarkdownInjector, bold, image, italic def get_customers(count: int = 1) -> Generator[dict]: response = requests.get( f"https://randomuser.me/api/?seed=markdown-toolkit&results={count}&nat=gb" ) for customer in response.json()["results"]: yield customer def customer_name(customer: dict) -> str: title = customer["name"]["title"] first = customer["name"]["first"] last = customer["name"]["last"] profile_photo = customer["picture"]["thumbnail"] return f"{image(uri=profile_photo)}<br>{title} {first} {last}" def customer_address(customer: dict) -> str: components = [ str(customer["location"]["street"]["number"]), customer["location"]["street"]["name"], customer["location"]["city"], customer["location"]["country"], bold(customer["location"]["postcode"]), ] return "<br>".join(components) with open("docs/examples/injection_source.md", "r", encoding="UTF-8") as file: source_document = MarkdownInjector(file) doc = MarkdownDocument() with doc.heading("Customers", level=2): doc.paragraph(f"List of Customers from the {italic('Database')}") with doc.table(titles=["Name", "Login", "Age", "Address"]) as table: for customer in get_customers(count=10): table.add_row( name=customer_name(customer), login=f'{customer["login"]["username"]} ({customer["email"]})', age=customer["dob"]["age"], address=customer_address(customer), ) source_document.anchors.customers.value = doc.render() print(source_document.render())
# Accounts This page shows the state of the active customers at Example Co. <!--- markdown-toolkit:customers ---> ## Customers List of Customers from the _Database_ | Name | Login | Age | Address | | --- | --- | --- | --- | | ![https://randomuser.me/api/portraits/thumb/women/84.jpg](https://randomuser.me/api/portraits/thumb/women/84.jpg)<br>Ms Heidi Martin | blueelephant929 (heidi.martin@example.com) | 75 | 875<br>Mill Road<br>York<br>United Kingdom<br>**AM4C 6GZ** | | ![https://randomuser.me/api/portraits/thumb/men/77.jpg](https://randomuser.me/api/portraits/thumb/men/77.jpg)<br>Mr Jeff Diaz | brownlion290 (jeff.diaz@example.com) | 74 | 2907<br>Queens Road<br>Bristol<br>United Kingdom<br>**EB1S 4HU** | | ![https://randomuser.me/api/portraits/thumb/women/34.jpg](https://randomuser.me/api/portraits/thumb/women/34.jpg)<br>Ms Leah Long | bigladybug864 (leah.long@example.com) | 49 | 5812<br>Stanley Road<br>Swansea<br>United Kingdom<br>**DO6Q 8UF** | | ![https://randomuser.me/api/portraits/thumb/women/83.jpg](https://randomuser.me/api/portraits/thumb/women/83.jpg)<br>Ms Grace Rose | goldenladybug266 (grace.rose@example.com) | 57 | 9037<br>The Green<br>Belfast<br>United Kingdom<br>**OC40 1GS** | | ![https://randomuser.me/api/portraits/thumb/men/35.jpg](https://randomuser.me/api/portraits/thumb/men/35.jpg)<br>Mr Christopher Edwards | happyzebra240 (christopher.edwards@example.com) | 46 | 3954<br>Park Road<br>Peterborough<br>United Kingdom<br>**K62 7LD** | | ![https://randomuser.me/api/portraits/thumb/men/57.jpg](https://randomuser.me/api/portraits/thumb/men/57.jpg)<br>Mr Darren Curtis | orangetiger489 (darren.curtis@example.com) | 47 | 3423<br>North Road<br>Wakefield<br>United Kingdom<br>**AY5F 3TF** | | ![https://randomuser.me/api/portraits/thumb/women/67.jpg](https://randomuser.me/api/portraits/thumb/women/67.jpg)<br>Mrs Lauren George | greenfish374 (lauren.george@example.com) | 47 | 7094<br>Main Road<br>Durham<br>United Kingdom<br>**D74 2WT** | | ![https://randomuser.me/api/portraits/thumb/men/46.jpg](https://randomuser.me/api/portraits/thumb/men/46.jpg)<br>Mr Jeffery Gutierrez | beautifulcat661 (jeffery.gutierrez@example.com) | 77 | 2771<br>Albert Road<br>Bangor<br>United Kingdom<br>**ZW0 6ZX** | | ![https://randomuser.me/api/portraits/thumb/women/9.jpg](https://randomuser.me/api/portraits/thumb/women/9.jpg)<br>Miss Alice Ruiz | crazyladybug440 (alice.ruiz@example.com) | 70 | 9347<br>Victoria Street<br>Truro<br>United Kingdom<br>**K5 1TB** | | ![https://randomuser.me/api/portraits/thumb/women/93.jpg](https://randomuser.me/api/portraits/thumb/women/93.jpg)<br>Ms Erin Williams | crazyostrich570 (erin.williams@example.com) | 39 | 6697<br>Windsor Road<br>York<br>United Kingdom<br>**LX5A 4PH** | <!--- markdown-toolkit:customers ---> _This page is regenerated by a script._
Accounts¶
This page shows the state of the active customers at Example Co.
Customers¶
List of Customers from the Database
Name Login Age Address
Ms Heidi Martinblueelephant929 (heidi.martin@example.com) 75 875
Mill Road
York
United Kingdom
AM4C 6GZ
Mr Jeff Diazbrownlion290 (jeff.diaz@example.com) 74 2907
Queens Road
Bristol
United Kingdom
EB1S 4HU
Ms Leah Longbigladybug864 (leah.long@example.com) 49 5812
Stanley Road
Swansea
United Kingdom
DO6Q 8UF
Ms Grace Rosegoldenladybug266 (grace.rose@example.com) 57 9037
The Green
Belfast
United Kingdom
OC40 1GS
Mr Christopher Edwardshappyzebra240 (christopher.edwards@example.com) 46 3954
Park Road
Peterborough
United Kingdom
K62 7LD
Mr Darren Curtisorangetiger489 (darren.curtis@example.com) 47 3423
North Road
Wakefield
United Kingdom
AY5F 3TF
Mrs Lauren Georgegreenfish374 (lauren.george@example.com) 47 7094
Main Road
Durham
United Kingdom
D74 2WT
Mr Jeffery Gutierrezbeautifulcat661 (jeffery.gutierrez@example.com) 77 2771
Albert Road
Bangor
United Kingdom
ZW0 6ZX
Miss Alice Ruizcrazyladybug440 (alice.ruiz@example.com) 70 9347
Victoria Street
Truro
United Kingdom
K5 1TB
Ms Erin Williamscrazyostrich570 (erin.williams@example.com) 39 6697
Windsor Road
York
United Kingdom
LX5A 4PHThis page is regenerated by a script.
Installation¶
Warning
This library hasn't reached API stability, when it does it'll be bumped to version 1.0.0
. Until then, make sure you pin your library versions.
To install the library directly for use in scripts you can install it directly with pip
:
If you want to include it in a larger poetry
project: