惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
Martin Fowler
Martin Fowler
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
B
Blog
U
Unit 42
B
Blog RSS Feed
D
DataBreaches.Net
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
腾讯CDC
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Visual Studio Blog
博客园 - 聂微东
MyScale Blog
MyScale Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
Engineering at Meta
Engineering at Meta

Chat SDK Documentation

History | Chat SDK History | Chat SDK List a vendor-official adapter | Chat SDK Approvals | Chat SDK Vercel Connect | Chat SDK Teams Low-Level APIs | Chat SDK CLI | Chat SDK Platform Adapters | Chat SDK State Adapters | Chat SDK Cards | Chat SDK Getting Started | Chat SDK Introduction | Chat SDK Modals | Chat SDK Slack Low-Level APIs | Chat SDK Streaming | Chat SDK Testing | Chat SDK Overview | Chat SDK toAiMessages | Chat SDK Cards | Chat SDK Overview | Chat SDK Modals | Chat SDK AI SDK Tools | Chat SDK Types | Chat SDK Message Subject | Chat SDK Conversation History | Chat SDK Transcripts | Chat SDK Slack bot with Next.js and Redis Actions | Chat SDK Direct Messages | Chat SDK Emoji | Chat SDK
Markdown | Chat SDK
Vercel · 2026-05-29 · via Chat SDK Documentation

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,
  tableToAscii, tableElementToAscii,
} from "chat";

The chat package re-exports mdast's union and content types so adapters and downstream code can build exhaustively-typed AST walkers without depending on mdast directly:

import type { Nodes, Root, Content } from "chat";

function render(node: Nodes): string {
  switch (node.type) {
    case "text": return node.value;
    case "strong": return node.children.map(render).join("");
    // ...
    default: throw new Error(`Unhandled: ${node satisfies never}`);
  }
}

Adapters use this pattern to make the type checker reject the build when a new mdast node type is introduced upstream.

root

Root node — the required top-level wrapper for an AST.

root([
  paragraph([text("Hello, world!")]),
])

paragraph

A paragraph block.

paragraph([text("Hello "), strong([text("world")])])

text

Plain text node.

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")

Hyperlink.

link("https://example.com", [text("click here")])
link("https://example.com", [text("click here")], "tooltip title")

blockquote

Block quotation.

blockquote([paragraph([text("Quoted text")])])

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"

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:

GuardMatches
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
isTableNode(node)Table
isTableRowNode(node)Table row
isTableCellNode(node)Table cell

getNodeChildren / getNodeValue

Safely access node properties without type narrowing.

const children = getNodeChildren(node); // Content[] | undefined
const value = getNodeValue(node);       // string | undefined

tableToAscii

Render an mdast Table node as a padded ASCII table string. Used by adapters that lack native table support (Google Chat, Discord, Telegram).

import { parseMarkdown, tableToAscii, isTableNode } from "chat";

const ast = parseMarkdown("| Name | Role |\n|------|------|\n| Alice | Engineer |");
// Find the table node and convert it

Output:

Name  | Role
------|--------
Alice | Engineer

tableElementToAscii

Render a table from headers and string row arrays as a padded ASCII table. Used for card TableElement fallback rendering.

import { tableElementToAscii } from "chat";

const ascii = tableElementToAscii(
  ["Name", "Age", "Role"],
  [
    ["Alice", "30", "Engineer"],
    ["Bob", "25", "Designer"],
  ]
);

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.

FeatureSlackTeamsGoogle Chat
Bold**text****text***text*
Italic_text__text__text_
Strikethrough~~text~~~~text~~~text~
Code`code``code``code`
Code blocks`````````
Links[text](url)[text](url)[text](url)
ListsSupportedSupportedSupported
Blockquotes>>Simulated with > prefix
TablesNative (markdown_text)Native GFMASCII fallback
Mentions<@USER><at>name</at><users/{id}>

Slack accepts standard markdown via the markdown_text field on chat.postMessage and friends, so the SDK passes markdown through directly. Incoming Slack messages still arrive as legacy mrkdwn (*bold*, <url|text>) and are parsed transparently. If you need to send mrkdwn yourself, use { raw: "..." }.

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.