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

推荐订阅源

F
Fortinet All Blogs
有赞技术团队
有赞技术团队
量子位
N
Netflix TechBlog - Medium
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
Google DeepMind News
Google DeepMind News
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
宝玉的分享
宝玉的分享
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
V
V2EX
IT之家
IT之家
L
LangChain Blog
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

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.