Skip to main content

A pure-Python library for programmatically generating Markdown files.

Project description

MarkdownPal

A pure-Python library for programmatically generating Markdown (.md) files via a clean, block-based document builder API.

Python License: MIT


Features

  • Block-based API — compose documents from typed, self-contained block objects
  • Inline formatting helpersbold(), italic(), code(), strikethrough()
  • Full block support — headings, paragraphs, quotes, code, lists, tables, images, links
  • Save to file — UTF-8 output with full support for international characters and emoji
  • Zero dependencies — no third-party packages required
  • Python 3.9+

Installation

pip3 install markdownpal

Quick Start

from markdownpal import Document
from markdownpal.blocks import H1Block, H2Block, TextBlock, CodeBlock, ULBlock
from markdownpal.inline import bold

doc = Document()

doc.append(H1Block("My Project"))
doc.append(TextBlock(f"A {bold('simple')} example of MarkdownPal."))
doc.append(H2Block("Installation"))
doc.append(CodeBlock("pip install markdownpal", lang="bash"))
doc.append(H2Block("Features"))
doc.append(ULBlock(["Zero dependencies", "Clean API", "Python 3.9+"]))

doc.save("output.md")

Output (output.md):

# My Project

A **simple** example of MarkdownPal.

## Installation

```bash
pip install markdownpal

Features

  • Zero dependencies
  • Clean API
  • Python 3.9+

---

## Block Reference

### Headings

```python
from markdownpal.blocks import H1Block, H2Block, H3Block, H4Block, H5Block, H6Block

doc.append(H1Block("Title"))       # # Title
doc.append(H2Block("Section"))     # ## Section
doc.append(H3Block("Subsection"))  # ### Subsection

Text

from markdownpal.blocks import TextBlock, QuoteBlock, HRBlock, CommentBlock

doc.append(TextBlock("A plain paragraph."))
doc.append(QuoteBlock("A blockquote.\nSpanning multiple lines."))
doc.append(HRBlock())                               # ---
doc.append(CommentBlock("Hidden in rendered output."))  # <!-- ... -->

Code

from markdownpal.blocks import CodeBlock

doc.append(CodeBlock("print('hello')", lang="python"))
doc.append(CodeBlock("SELECT * FROM users;", lang="sql"))
doc.append(CodeBlock("no language specified"))

Lists

from markdownpal.blocks import ULBlock, OLBlock, TaskListBlock

doc.append(ULBlock(["Apples", "Bananas", "Cherries"]))

doc.append(OLBlock(["Install", "Configure", "Run"]))

doc.append(TaskListBlock([
    ("Write tests", True),
    ("Write code", True),
    ("Deploy",      False),
]))

Table

from markdownpal.blocks import TableBlock

doc.append(TableBlock(
    headers=["Name", "Role", "Status"],
    rows=[
        ["Alice", "Engineer", "Active"],
        ["Bob",   "Designer", "Active"],
    ]
))

Images & Links

from markdownpal.blocks import ImageBlock, LinkBlock

doc.append(ImageBlock(src="logo.png", alt="Project Logo"))
doc.append(LinkBlock(text="Documentation", url="https://example.com/docs"))

Inline Helpers

Inline helpers return plain strings and can be embedded inside any block content:

from markdownpal.inline import bold, italic, code, strikethrough

bold("important")            # **important**
italic("note")               # *note*
code("os.path.join()")       # `os.path.join()`
strikethrough("deprecated")  # ~~deprecated~~

# Composable
bold(italic("emphasis"))     # ***emphasis***

# Embed in blocks
doc.append(TextBlock(f"Call {code('render()')} to get the output string."))

Document API

doc = Document()
doc.append(block)   # Add a Block instance
doc.render()        # Returns the full Markdown string
doc.save("out.md")  # Writes UTF-8 Markdown file to disk

append() raises TypeError if the argument is not a Block instance.
render() joins all blocks with a blank line (\n\n) between them.


Project Structure

markdownpal/
├── __init__.py          # Top-level public API
├── document.py          # Document class
├── inline.py            # Inline format helpers
└── blocks/
    ├── base.py          # Block abstract base class
    ├── heading.py       # H1Block ~ H6Block
    ├── text.py          # TextBlock, QuoteBlock, HRBlock, CommentBlock
    ├── code.py          # CodeBlock
    ├── list_.py         # ULBlock, OLBlock, TaskListBlock
    ├── table.py         # TableBlock
    └── media.py         # ImageBlock, LinkBlock

Development

# Clone the repository
git clone https://github.com/rogerstacker/markdownpal.git
cd markdownpal

# Install dev dependencies
pip3 install -e ".[dev]"

# Run tests
pytest

License

MIT © 2026 Rogerstacker

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

markdownpal-0.1.1.tar.gz (8.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

markdownpal-0.1.1-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file markdownpal-0.1.1.tar.gz.

File metadata

  • Download URL: markdownpal-0.1.1.tar.gz
  • Upload date:
  • Size: 8.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for markdownpal-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a7a1b6d1c0257f6cebdb4f3552f493ff6f68d0145a5b6c6e122b63e3da476a0a
MD5 3747411b579ab2f911e3ba02b4c3c63a
BLAKE2b-256 517a69c3e7aeb4322e728c37359efb6eeb3606d90c95c194ff12cbb50d5efb4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for markdownpal-0.1.1.tar.gz:

Publisher: publish.yml on rogerstacker/markdownpal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file markdownpal-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: markdownpal-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for markdownpal-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0c82d0ba6defee1e27bfc4b61a4142ab1bbd04ac4113a0748d7e628c165cb87a
MD5 d1d20b2d88f4a34351571ba85ae59f6e
BLAKE2b-256 df3e26fb1e70aa7125ba9a3c94dd2e56623658f838e96bb3fa93b26a860bdcf4

See more details on using hashes here.

Provenance

The following attestation bundles were made for markdownpal-0.1.1-py3-none-any.whl:

Publisher: publish.yml on rogerstacker/markdownpal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page