Markdown
AST builder functions and utilities for programmatic message formatting.
The SDK uses mdast (Markdown AST) as the canonical format for message formatting. Each adapter converts the AST to the platform's native format.
import {
root, paragraph, text, strong, emphasis, strikethrough,
inlineCode, codeBlock, link, blockquote,
parseMarkdown, stringifyMarkdown, toPlainText, walkAst,
} from "chat";Node builders
root
Root node — the required top-level wrapper for an AST.
root([
paragraph([text("Hello, world!")]),
])Prop
Type
paragraph
A paragraph block.
paragraph([text("Hello "), strong([text("world")])])text
Plain text node.
text("Hello, world!")strong
Bold text.
strong([text("important")])emphasis
Italic text.
emphasis([text("emphasized")])strikethrough
Strikethrough text.
strikethrough([text("removed")])inlineCode
Inline code span.
inlineCode("const x = 1")codeBlock
Fenced code block with optional language.
codeBlock("const x = 1;", "typescript")Prop
Type
link
Hyperlink.
link("https://example.com", [text("click here")])
link("https://example.com", [text("click here")], "tooltip title")Prop
Type
blockquote
Block quotation.
blockquote([paragraph([text("Quoted text")])])Parsing and stringifying
parseMarkdown
Parse a markdown string into an mdast AST.
const ast = parseMarkdown("**Hello** world");stringifyMarkdown
Convert an mdast AST back to a markdown string.
const md = stringifyMarkdown(ast); // "**Hello** world"toPlainText
Strip all formatting and return plain text.
const plain = toPlainText(ast); // "Hello world"markdownToPlainText
Shorthand for parsing markdown and extracting plain text.
const plain = markdownToPlainText("**Hello** world"); // "Hello world"AST utilities
walkAst
Transform an AST by visiting each node. Return a new value to replace the node, or undefined to keep it unchanged.
const transformed = walkAst(ast, (node) => {
if (isStrongNode(node)) {
return emphasis(getNodeChildren(node));
}
return undefined;
});Type guards
Functions for checking node types:
| Guard | Matches |
|---|---|
isTextNode(node) | Plain text |
isParagraphNode(node) | Paragraph |
isStrongNode(node) | Bold |
isEmphasisNode(node) | Italic |
isDeleteNode(node) | Strikethrough |
isInlineCodeNode(node) | Inline code |
isCodeNode(node) | Code block |
isLinkNode(node) | Link |
isBlockquoteNode(node) | Blockquote |
isListNode(node) | List |
isListItemNode(node) | List item |
getNodeChildren / getNodeValue
Safely access node properties without type narrowing.
const children = getNodeChildren(node); // Content[] | undefined
const value = getNodeValue(node); // string | undefinedPlatform formatting
The SDK uses mdast as the canonical format and each adapter converts it to the platform's native syntax. You write standard markdown and the SDK handles the translation — but it helps to know how each platform renders common formatting.
| Feature | Slack | Teams | Google Chat |
|---|---|---|---|
| Bold | *text* | **text** | *text* |
| Italic | _text_ | _text_ | _text_ |
| Strikethrough | ~text~ | ~~text~~ | ~text~ |
| Code | `code` | `code` | `code` |
| Code blocks | ``` | ``` | ``` |
| Links | <url|text> | [text](url) | [text](url) |
| Lists | Supported | Supported | Supported |
| Blockquotes | > | > | Simulated with > prefix |
| Mentions | <@USER> | <at>name</at> | <users/{id}> |
You don't need to worry about these differences when using the SDK — the AST builders and parseMarkdown handle conversion automatically. This table is useful if you're working with raw platform payloads or debugging formatting issues.