Skip to main content

Convert Markdown to Slack Block Kit blocks using mistletoe

Project description

Slack Blocks Markdown

PyPI version Python 3.11+ License: MIT Tests

Convert Markdown to Slack Block Kit blocks using Python. This library provides a clean, efficient way to transform your Markdown content into Slack's interactive Block Kit format.

Features

  • 🚀 Complete Markdown Support: Headers, paragraphs, lists, code blocks, quotes, tables, links, and inline formatting
  • 📱 Slack Block Kit Compatible: All blocks follow official Slack specifications with proper constraints
  • 🎯 Custom Table Support: Full implementation of Slack's table blocks with validation
  • 🔧 Flexible APIs: Dictionary-based for simplicity, object-based for editing, or direct renderer for full control
  • ✏️ Editable Blocks: Modify generated blocks before sending to Slack
  • High Performance: Efficient processing of large documents
  • 🧪 Well Tested: Comprehensive test suite with high coverage
  • 📝 Type Safe: Full type hints for better development experience

Installation

pip install slack-blocks-markdown

Quick Start

Simple Usage (Dictionary API)

from slack_blocks_markdown import markdown_to_blocks

# Convert markdown to Slack blocks (returns list of dictionaries)
markdown = """# Project Update

This is a **bold** announcement about our new features:

- ✅ User authentication
- ✅ Real-time updates
- 🚧 Mobile app (coming soon)

> **Note**: This is still in beta, so please report any issues!
"""

blocks = markdown_to_blocks(markdown)
print(f"Generated {len(blocks)} blocks")

# Use blocks directly with Slack SDK
from slack_sdk import WebClient

client = WebClient(token="your-token")
client.chat_postMessage(
    channel="#general",
    blocks=blocks
)

Object-Based API (Editable Blocks)

from slack_blocks_markdown import markdown_to_block_objects

# Convert markdown to Block objects that can be modified
markdown = "# Hello World\n\nThis is a paragraph."

blocks = markdown_to_block_objects(markdown)

# Edit blocks before sending to Slack
blocks[0].text.text = "Custom Header"
blocks[1].text.text = "Modified paragraph with *custom* content."

# Convert to dictionaries when ready to send
from slack_sdk import WebClient

client = WebClient(token="your-token")
client.chat_postMessage(
    channel="#general",
    blocks=[block.to_dict() for block in blocks]
)

Advanced Usage (Direct Renderer)

For maximum control over the rendering process, use the renderer directly:

from mistletoe import Document
from slack_blocks_markdown import SlackBlocksRenderer

# Direct renderer usage with options
with SlackBlocksRenderer(expand_sections=True) as renderer:
    document = Document(markdown)
    blocks = renderer.render(document)  # Returns Block objects

# Convert to dictionaries for JSON serialization
blocks_json = [block.to_dict() for block in blocks]

Supported Markdown Elements

Markdown Element Slack Block Type Notes
# Headers HeaderBlock Truncated to 150 chars
Paragraphs SectionBlock With mrkdwn formatting
**Bold***Bold* Inline formatting Slack markdown style
_Italic__Italic_ Inline formatting Slack markdown style
`Code``Code` Inline formatting Preserved
~~Strike~~~Strike~ Inline formatting Slack markdown style
[Link](url)<url|Link> Inline formatting Slack link format
Code blocks SectionBlock With triple backticks
> Blockquotes SectionBlock With > prefix
Lists SectionBlock Bullet (•) or numbered
Tables TableBlock Custom implementation
--- DividerBlock Horizontal rules

Examples

Basic Formatting

markdown = "This is **bold** and _italic_ with `code` and [links](https://example.com)"
blocks = markdown_to_blocks(markdown)
# Result: [{"type": "section", "text": {"type": "mrkdwn", "text": "This is *bold* and _italic_ with `code` and <https://example.com|links>"}}]

Lists and Code

markdown = """
## Features

- Easy to use
- Fast processing
- Great documentation

```python
def hello():
    return "world"

""" blocks = markdown_to_blocks(markdown)

Generates HeaderBlock, SectionBlock (list), and SectionBlock (code)


### Tables

```python
markdown = """
| Feature | Status |
|---------|--------|
| Auth | ✅ Done |
| API | 🚧 Progress |
"""
blocks = markdown_to_blocks(markdown)
# Generates custom TableBlock with proper cell structure

Editing Blocks (Object-Based API)

from slack_blocks_markdown import markdown_to_block_objects

# Generate blocks from markdown
markdown = """# Project Status

Current progress:

- Feature A: Complete
- Feature B: In progress
"""

blocks = markdown_to_block_objects(markdown)

# Modify the header dynamically
project_name = "My Awesome Project"
blocks[0].text.text = f"{project_name} - Status Report"

# Add a timestamp to the paragraph
from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
blocks[1].text.text = f"Report generated at {timestamp}\n\n" + blocks[1].text.text

# Convert to dictionaries and send
from slack_sdk import WebClient
client = WebClient(token="your-token")
client.chat_postMessage(
    channel="#general",
    blocks=[block.to_dict() for block in blocks]
)

Combining Manual and Generated Blocks

from slack_blocks_markdown import markdown_to_block_objects
from slack_sdk.models.blocks import DividerBlock, SectionBlock, MarkdownTextObject

# Generate blocks from markdown
markdown = "## Summary\n\nProject is on track."
generated_blocks = markdown_to_block_objects(markdown)

# Create custom blocks manually
custom_header = SectionBlock(
    text=MarkdownTextObject(text="*Custom Section*")
)

# Combine blocks in any order
all_blocks = [
    custom_header,
    DividerBlock(),
    *generated_blocks,  # Insert all generated blocks
]

# Send to Slack
client.chat_postMessage(
    channel="#general",
    blocks=[block.to_dict() for block in all_blocks]
)

API Reference

markdown_to_blocks(markdown_text: str, expand_sections: bool | None = None) -> list[dict[str, Any]]

Convenience function to convert markdown to Slack block dictionaries.

Parameters:

  • markdown_text: Markdown formatted string
  • expand_sections: (Optional) Control section block expansion
    • True: Force all section blocks to be fully expanded
    • False: Allow Slack to show "Show more" button for long content
    • None (default): Use Slack's default behavior

Returns:

  • List of Slack block dictionaries ready for API use

Example:

blocks = markdown_to_blocks("# Hello\n\nWorld", expand_sections=True)
client.chat_postMessage(channel="#general", blocks=blocks)

markdown_to_block_objects(markdown_text: str, expand_sections: bool | None = None) -> list[Block]

Convert markdown to editable Slack Block objects.

Parameters:

  • markdown_text: Markdown formatted string
  • expand_sections: (Optional) Control section block expansion (same as above)

Returns:

  • List of Block objects from slack_sdk that can be modified

Example:

blocks = markdown_to_block_objects("# Hello\n\nWorld")
blocks[0].text.text = "Modified Header"  # Edit blocks
block_dicts = [b.to_dict() for b in blocks]  # Convert when ready

Use Cases:

  • Modify generated blocks before sending
  • Add dynamic content to specific blocks
  • Combine with custom block creation
  • Inspect block structure programmatically

SlackBlocksRenderer

Main renderer class inheriting from mistletoe's BaseRenderer.

Parameters:

  • expand_sections: (Optional) Control section block expansion behavior

Methods:

  • render(document): Convert mistletoe Document to list of Block objects
  • Context manager support for proper resource handling

Example:

from mistletoe import Document
with SlackBlocksRenderer(expand_sections=True) as renderer:
    document = Document(markdown_text)
    blocks = renderer.render(document)

TableBlock

Custom table block implementation for Slack Block Kit.

Parameters:

  • rows: List of rows (each row is list of cell objects)
  • block_id: Optional unique identifier (max 255 chars)
  • column_settings: Optional column configuration

Slack Block Kit Constraints

This library automatically handles Slack's Block Kit constraints:

  • Headers: Maximum 150 characters (truncated with "..." if longer)
  • Text blocks: Maximum 3000 characters (truncated with "..." if longer)
  • Tables: Maximum 100 rows, 20 columns per row
  • Block IDs: Maximum 255 characters

Development

# Clone repository
git clone https://github.com/atacan/slack-blocks-markdown.git
cd slack-blocks-markdown

# Install with development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
ruff check src/ tests/
black src/ tests/

# Run type checking
mypy src/

Testing

The library includes comprehensive tests covering:

  • All markdown element types
  • Slack constraint validation
  • Edge cases and error handling
  • Integration with Slack API format
  • Performance with large documents
# Run with coverage
pytest --cov=slack_blocks_markdown --cov-report=html

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Changelog

See CHANGELOG.md for version history.

Related Projects

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

slack_blocks_markdown-0.2.1.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

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

slack_blocks_markdown-0.2.1-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file slack_blocks_markdown-0.2.1.tar.gz.

File metadata

  • Download URL: slack_blocks_markdown-0.2.1.tar.gz
  • Upload date:
  • Size: 24.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for slack_blocks_markdown-0.2.1.tar.gz
Algorithm Hash digest
SHA256 c623913e0590bdc097b74697857dbf3c4b93525f6ba2100cfeb2445f1c36da7f
MD5 48f2ca44f782b59e1926c3c73156d833
BLAKE2b-256 afd7aa1990f8e24a38202df2d64dbaf58955f25a1eda6185e96e513ffe30cbc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for slack_blocks_markdown-0.2.1.tar.gz:

Publisher: publish.yml on atacan/slack-blocks-markdown

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

File details

Details for the file slack_blocks_markdown-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for slack_blocks_markdown-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 620332d365f80161c81b27cb15ae573d4c097d12768becc75219d01b35f53c3d
MD5 2d02be8e518e7e82dc7bce42a68fe619
BLAKE2b-256 7f28bf7fe4eb5f6a5a0c2bf673f43410335b9eb2db687c767d0ee8c875e540ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for slack_blocks_markdown-0.2.1-py3-none-any.whl:

Publisher: publish.yml on atacan/slack-blocks-markdown

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