Skip to main content

Convert LLM Markdown into Slack Block Kit markdown/table messages

Project description

slack-markdown-parser

slack-markdown-parser is a Python library that converts standard Markdown generated by LLMs into Slack Block Kit messages built from markdown and table blocks.

Why this library exists

Many Slack AI bots have traditionally converted model output into Slack-specific mrkdwn, but that approach creates a few recurring problems:

  • Conversion overhead: LLMs naturally generate standard Markdown, so mrkdwn usually requires extra transformation logic or prompt constraints.
  • Unstable formatting in languages without word spacing: in Japanese and similar scripts, Slack can fail to interpret *, ~, and related markers correctly, exposing the raw punctuation.
  • No table syntax in mrkdwn: Markdown tables need custom fallback rendering if you stay in the old format.

Design approach

This library leans on Slack Block Kit's markdown block for standard Markdown and table block for tables.

Problem Approach
Conversion overhead Send standard Markdown through Slack markdown blocks without rewriting it into mrkdwn.
Formatting instability Prefer zero-width spaces (ZWSP, U+200B) around formatting tokens, and fall back to locale-aware visible-space padding for CJK nested inline-code cases where Slack rendering still breaks.
No table syntax in mrkdwn Detect Markdown tables and convert them into Slack table blocks, including repair of common LLM-generated table inconsistencies.

The target is natural rendering on Slack, not full CommonMark or HTML fidelity. If Slack itself does not support a construct in markdown blocks, this library prefers safe plain-text rendering or explicit table blocks over aggressive rewrites into old mrkdwn.

Features

  • Convert standard Markdown into Slack markdown blocks
  • Convert Markdown tables into Slack table blocks
  • Repair common LLM table issues such as missing outer pipes, missing separator rows, mismatched column counts, and empty cells
  • Split output into multiple Slack messages when needed to satisfy Slack's "one table per message" constraint
  • Sanitize ANSI/control characters and neutralize invalid Slack angle-bracket tokens before block generation
  • Add ZWSP around inline formatting tokens to reduce rendering issues outside fenced code blocks
  • Use locale-aware visible-space padding for nested inline-code emphasis in dense Japanese, Chinese, and Korean text when Slack requires stronger boundaries than ZWSP alone
  • Support Markdown and Slack-style links inside table cells
  • Build fallback text for chat.postMessage.text from generated blocks, normalizing synthetic ZWSP and any parser-inserted visible-space padding used only for rendering stability
  • Accept raw LLM Markdown without tightly constraining the model prompt, using best-effort sanitize and table repair before Slack delivery

Observed Slack behavior

The library is built around how Slack actually renders markdown and table blocks in practice.

Reliable in current Slack rendering:

  • **bold**, *italic*, ~~strike~~, inline code, and fenced code blocks
  • Bare URLs, autolinks, Markdown links, reference-style links, and mailto links
  • Bullet lists, ordered lists, task lists, and simple blockquotes
  • Explicit Slack table blocks generated from Markdown tables

Known Slack-side limitations:

  • Heading syntax (#, setext headings) renders as plain text rather than true heading levels
  • Nested blockquotes are weak compared with full Markdown renderers
  • Horizontal rules render more like line text than semantic separators
  • Markdown image syntax does not become an embedded image in markdown blocks
  • Math, raw HTML, HTML comments, <details>, admonition syntax, and Mermaid are rendered as plain text or code, not as rich features

What this library compensates for:

  • Normalizes underscore emphasis (_..._, __...__) into Slack-friendly asterisk emphasis
  • Wraps bare URLs into Slack-friendly autolink form before sending markdown blocks
  • Repairs malformed LLM-generated tables before converting them into Slack table blocks
  • Keeps table-like rows inside fenced code blocks out of table normalization
  • Neutralizes invalid Slack angle-bracket tokens such as raw HTML-like tags

Requirements

  • Your Slack integration must support Block Kit payloads with markdown and table blocks.
  • This library does not help when your delivery path only accepts plain text or mrkdwn strings.

Installation

pip install slack-markdown-parser

Quick start

from slack_markdown_parser import (
    convert_markdown_to_slack_payloads,
)

markdown = """
# Weekly Report

| Team | Status |
|---|---|
| API | **On track** |
| UI | *In progress* |
"""

for payload in convert_markdown_to_slack_payloads(markdown):
    print(payload)

convert_markdown_to_slack_messages automatically splits output into multiple messages when the input contains multiple tables.

Rendering example

Example input:

# Weekly Product Update

This week we worked on **search performance** and *UI polish*. The old flow is ~~scheduled for removal~~.
The detailed log ID is `run-20260305-02`.
Reference: https://example.com/changelog

- Improved **API response time**
  - Increased *cache hit rate*
  - Adjusted timeout settings
- Stabilized batch processing
  - Unified retry counts
- Updated documentation

Category | Status | Owner
API | **In progress** | Team A
UI | *Under review* | Team B
QA | ~~On hold~~ | Team C

> Note: production rollout is scheduled for 2026-03-08 10:00 JST

1. Finalize release notes
   1. Unify change labels
   2. Add impact notes
2. Tune monitoring alert thresholds
   1. Update the `warning` threshold
3. Re-check QA

```bash
./deploy.sh production
```

Example Slack bot rendering (markdown + table blocks):

Slack BOT rendering example

Public API

Main functions

Function Description
convert_markdown_to_slack_messages(markdown_text) -> list[list[dict]] Convert Markdown into Slack messages already split around table blocks.
convert_markdown_to_slack_payloads(markdown_text) -> list[dict] Convert Markdown into Slack-ready payloads with both blocks and fallback text.
convert_markdown_to_slack_blocks(markdown_text) -> list[dict] Convert Markdown into a flat Block Kit block list.
build_fallback_text_from_blocks(blocks) -> str Build fallback text suitable for chat.postMessage.text.
blocks_to_plain_text(blocks) -> str Convert blocks into plain text.

Utility functions

Function Description
normalize_markdown_tables(markdown_text) -> str Normalize Markdown table syntax before conversion.
add_zero_width_spaces_to_markdown(text) -> str Insert ZWSP around formatting tokens where Slack needs stronger boundaries.
decode_html_entities(text) -> str Decode HTML entities before parsing.
sanitize_slack_text(text) -> str Remove ANSI/control noise and neutralize invalid Slack angle-bracket tokens.
strip_zero_width_spaces(text) -> str Remove ZWSP (U+200B) and BOM (U+FEFF) while preserving join-control characters such as ZWJ.

Lower-level exported helpers

These are also part of the public package surface:

  • add_zero_width_spaces
  • convert_markdown_text_to_blocks
  • extract_plain_text_from_table_cell
  • markdown_table_to_slack_table
  • parse_markdown_table
  • split_blocks_by_table
  • split_markdown_into_segments

Specification and scope

Contributing

Contributions, bug reports, and documentation improvements are welcome. Please read CONTRIBUTING.md before opening an issue or pull request.

Changelog

Version history is maintained in CHANGELOG.md.

Contact

License

MIT

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_markdown_parser-2.2.4.tar.gz (44.8 kB view details)

Uploaded Source

Built Distribution

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

slack_markdown_parser-2.2.4-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file slack_markdown_parser-2.2.4.tar.gz.

File metadata

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

File hashes

Hashes for slack_markdown_parser-2.2.4.tar.gz
Algorithm Hash digest
SHA256 de1ebf3ae1655e8c643c699efbc370709b3e3159f2f972cd59bda6ba8695b095
MD5 b41c880ef738f343c4b22c0e17949179
BLAKE2b-256 462525170cbc0800fd3cfe77dd6b23522fccab781534f8a09683d6e9554d5e4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for slack_markdown_parser-2.2.4.tar.gz:

Publisher: publish.yml on darkgaldragon/slack-markdown-parser

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_markdown_parser-2.2.4-py3-none-any.whl.

File metadata

File hashes

Hashes for slack_markdown_parser-2.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 4877e703e2f45ef14c790b314759dcb8c2d388cebe8026e28391d2f59ccd89a9
MD5 2e29a88a33df38ff299166154b061071
BLAKE2b-256 fcab932a3454a778e32fd563dbf5832326a4b7e5dc7b68477546cb07179e6628

See more details on using hashes here.

Provenance

The following attestation bundles were made for slack_markdown_parser-2.2.4-py3-none-any.whl:

Publisher: publish.yml on darkgaldragon/slack-markdown-parser

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