npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

md-to-slack-blocks

v1.0.0

Published

Convert Markdown to Slack Block Kit blocks with full formatting support

Readme

md-to-slack-blocks

Convert Markdown to Slack Block Kit blocks with full formatting support.

npm version License: MIT

Features

  • Full Markdown Support: Headers, lists, tables, code blocks, blockquotes, and inline formatting
  • Rich Text Output: Uses Slack's rich_text blocks for optimal formatting
  • Table Support: Converts Markdown tables to Slack's table blocks with rich text cells
  • Multiple Tables: Handles Slack's 1-table-per-message limit by splitting into multiple block arrays
  • TypeScript: Full type definitions included
  • Zero Dependencies: Only peer dependency is @slack/types for type definitions

Installation

npm install md-to-slack-blocks
# or
yarn add md-to-slack-blocks
# or
pnpm add md-to-slack-blocks
# or
bun add md-to-slack-blocks

Quick Start

import { markdownToSlackBlocks } from 'md-to-slack-blocks';

const 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!
`;

const blocks = markdownToSlackBlocks(markdown);

// Use with Slack SDK
await client.chat.postMessage({
  channel: '#general',
  blocks: blocks,
  text: 'Project Update', // Fallback text
});

API Reference

markdownToSlackBlocks(markdown, options?)

Converts a Markdown string to an array of Slack blocks.

import { markdownToSlackBlocks } from 'md-to-slack-blocks';

const blocks = markdownToSlackBlocks('# Hello **World**');

Parameters:

  • markdown (string): The Markdown text to convert
  • options (MarkdownConverterOptions, optional): Conversion options

Returns: SlackBlock[] - Array of Slack blocks ready to use with the Slack API

markdownToSlackBlocksMultiple(markdown, options?)

Converts Markdown to multiple block arrays, splitting when multiple tables are present. This is necessary because Slack only allows one table per message.

import { markdownToSlackBlocksMultiple } from 'md-to-slack-blocks';

const markdown = `
# Report

| Table 1 | Col |
|---------|-----|
| Data    | A   |

| Table 2 | Col |
|---------|-----|
| Data    | B   |
`;

const blockArrays = markdownToSlackBlocksMultiple(markdown);

// Send as multiple messages
for (const blocks of blockArrays) {
  await client.chat.postMessage({
    channel: '#general',
    blocks: blocks,
  });
}

markdownToSlackBlocksWithMetadata(markdown, options?)

Converts Markdown and returns metadata including any conversion warnings.

import { markdownToSlackBlocksWithMetadata } from 'md-to-slack-blocks';

const result = markdownToSlackBlocksWithMetadata(markdown);

if (result.warnings?.length) {
  console.warn('Conversion warnings:', result.warnings);
}

// Use result.blocks

markdownToSlackBlocksJson(markdown, options?)

Converts Markdown to plain JSON objects (useful for serialization).

import { markdownToSlackBlocksJson } from 'md-to-slack-blocks';

const blocksJson = markdownToSlackBlocksJson(markdown);
const jsonString = JSON.stringify(blocksJson);

MarkdownConverter Class

A class wrapper for persistent options across multiple conversions.

import { MarkdownConverter } from 'md-to-slack-blocks';

const converter = new MarkdownConverter({
  maxHeaderLength: 100,
  maxTableRows: 50,
});

const blocks1 = converter.convert('# Title 1');
const blocks2 = converter.convert('# Title 2');

// Update options
converter.setOptions({ maxTableColumns: 10 });

Options

interface MarkdownConverterOptions {
  // Whether to expand all section blocks by default (default: true)
  expandSections?: boolean;

  // Maximum header text length - Slack limit is 150 (default: 150)
  maxHeaderLength?: number;

  // Maximum section text length - Slack limit is 3000 (default: 3000)
  maxSectionLength?: number;

  // Maximum table rows - Slack limit is 100 (default: 100)
  maxTableRows?: number;

  // Maximum table columns - Slack limit is 20 (default: 20)
  maxTableColumns?: number;
}

Supported Markdown

Block Elements

| Markdown | Slack Block | |----------|-------------| | # Heading | Bold text in rich_text_section | | ## Heading 2 | Bold text in rich_text_section | | Paragraphs | rich_text_section | | - List item | rich_text_list (bullet) | | 1. Numbered | rich_text_list (ordered) | | ```code``` | rich_text_preformatted | | > Blockquote | rich_text_quote | | --- | divider | | Tables | table with rich_text cells |

Inline Elements

| Markdown | Rendered As | |----------|-------------| | **bold** | Bold text | | *italic* or _italic_ | Italic text | | ~~strikethrough~~ | Strikethrough text | | `code` | Inline code | | [link](url) | Clickable link | | ![alt](url) | Link to image |

Tables with Formatting

Tables support full Markdown formatting within cells:

| Feature | Status | Notes |
|---------|--------|-------|
| **Auth** | `done` | _Shipped in v1.0_ |
| [Docs](url) | `pending` | See **roadmap** |

Advanced Usage

Low-Level API

For advanced use cases, you can access the parser and builder directly:

import { MarkdownParser, SlackBlockBuilder } from 'md-to-slack-blocks';

const parser = new MarkdownParser(markdown);
const ast = parser.parse();

// Inspect or modify the AST
console.log(ast);

const builder = new SlackBlockBuilder({ maxTableRows: 50 });
const blocks = builder.buildBlocks(ast);

AST Types

import type { MarkdownNode, MarkdownElementType } from 'md-to-slack-blocks';

// The AST node structure
interface MarkdownNode {
  type: MarkdownElementType;
  content?: string;
  children?: MarkdownNode[];
  attributes?: Record<string, any>;
}

Slack API Limits

This library respects Slack's API limits:

  • 50 blocks per message (warning issued if exceeded)
  • 1 table per message (use markdownToSlackBlocksMultiple for multiple tables)
  • 100 rows per table
  • 20 columns per table
  • 150 characters for header text
  • 3000 characters per section

Examples

Daily Standup Bot

const markdown = `
# Daily Standup - ${new Date().toLocaleDateString()}

**Completed:**
- Finished user authentication
- Fixed bug #123

**In Progress:**
- Working on API endpoints

**Blockers:**
> Waiting for design review

---
_Posted automatically_
`;

const blocks = markdownToSlackBlocks(markdown);

PR Notification

const markdown = `
## Pull Request #${prNumber}

**${prTitle}**

${prDescription}

| Stat | Value |
|------|-------|
| Files changed | ${filesChanged} |
| Additions | +${additions} |
| Deletions | -${deletions} |

[View PR](${prUrl})
`;

const blocks = markdownToSlackBlocks(markdown);

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT - see LICENSE for details.

Credits

Built with love by Midlyr.