代码示例
用于渲染 LLM 返回的流式 Markdown。下面按 @ant-design/x-markdown@2.0.0 的「代码示例」排列。每一则都是 Vue 已经实现的能力。
可编辑的预览在 在线体验,和基础用法是同一块输入框。
基础用法
Hello World
Welcome to XMarkdown!
- Item 1
- Item 2
- Item 3
const a = 1;
流式处理
Status: idle
插件使用
plugin
Ship the TODO before Friday.
自定义组件
Custom Blue Title
Normal H2
Paragraph with bold and italic.
公式
Pythagoras: .
代码高亮
A fenced block picks up the language class:
tsexport const answer = 42;
Inline const x = 1 stays a plain code tag.
Mermaid
```mermaid graph TD A[Start] --> B[Answer] ```
主题
自定义标记 tokenizer
Level 1 Heading
Level 2 Heading
Level 3 Heading
Level 4 Heading
标记处理 walkTokens
Please check: Invalid link
渲染前处理 renderer
🚀 Render Code Text
<html><form><button>Test</button><form></html>中文链接处理
Untreated
Treated
XSS 防御
Cross-Site Scripting (XSS) Attack Vectors
1. Stored XSS (Persistent XSS)
2. Reflected XSS (Non-persistent XSS)
3. DOM-based XSS
4. Attribute-based XSS
5. Script Tag Injection
6. Event Handler XSS

7. JavaScript Protocol XSS
8. SVG Vector XSS
9. Form Input XSS
10. CSS Injection XSS
Test Content
11. Data URI XSS
12. Mouse Event XSS
Hover over this text
13. Button Tag XSS
14. Nested script evasion
流式语法
Markdown Source
Click Re-Render to start
Rendered Output
流式动画
新标签页打开链接
openLinksInNewTab enabled
Default (same tab)
思考过程
Check the constraint, then answer.
The answer is 42.
API
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| content | 要渲染的 Markdown 内容 | string | - |
| children | Markdown 内容,content 的别名 | string | - |
| components | 用自定义 Vue 组件替换 HTML / 自定义标签,详见 组件总览 | Record<string, Component> | - |
| paragraphTag | 段落使用的 HTML 标签。自定义组件含块级元素时可改成 div,避免非法嵌套 | string | 'p' |
| streaming | 流式渲染配置,见 流式语法 | boolean | StreamingOption | - |
| config | marked 解析与扩展配置 | MarkedExtension | { gfm: true } |
| plugins | 兼容旧写法:带 transform(content) 的对象会在解析前改写字符串;优先用 config + marked extensions | any[] | - |
| openLinksInNewTab | 是否给所有 a 标签加上 target="_blank"(以及 rel="noopener noreferrer") | boolean | false |
| dompurifyConfig | DOMPurify 配置,用于 HTML 消毒与 XSS 防护 | DOMPurify.Config | - |
| className | 根节点额外 CSS 类名 | string | - |
| rootClassName | className 的别名 | string | - |
| style | 根节点内联样式 | CSSProperties | - |
| prefixCls | CSS 类名前缀覆盖 | string | - |
StreamingOption
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| hasNextChunk | 后面是否还有 chunk。为 false 时刷新缓存并完成渲染 | boolean | false |
| enableAnimation | 为块级元素(p、li、h1–h4)启用文字淡入 | boolean | false |
| animationConfig | 文字出现动画配置 | AnimationConfig | { fadeDuration: 200, easing: 'ease-in-out' } |
| incompleteMarkdownComponentMap | 未完成语法对应的自定义组件名。流式输出遇到未闭合的链接、表格、HTML 等时,可用占位 / loading 组件包裹片段 | Partial<Record<Exclude<StreamCacheTokenType, 'text'>, string>> | {} |
AnimationConfig
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| fadeDuration | 淡入动画时长(毫秒) | number | 200 |
| easing | 缓动函数 | string | 'ease-in-out' |
ComponentProps
自定义 components 映射组件收到的入参:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| domNode | 解析后的 DOM 节点信息(标签名、属性、子节点结构) | DOMNode | - |
| streamStatus | 流式状态:loading 表示该块仍在输出,done 表示已闭合。目前主要覆盖 HTML 与围栏代码;缩进代码块没有明确结束符,始终为 done。code 也可读 data-state | 'loading' | 'done' | - |
| block | 仅 code:data-block="true" 时为块级代码 | boolean | - |
| children | 组件包裹的内容 | VNode[] | string | - |
| 其余 | 标准 HTML 属性(href、title、class / className 等)与自定义 data-* | Record<string, any> | - |
StreamCacheTokenType
与源码 StreamCacheTokenType 枚举一致(注意是 html,不是文档旧稿里的 heading / xml):
ts
type StreamCacheTokenType =
| 'text' // 纯文本
| 'link' // 链接 [text](url)
| 'image' // 图片 
| 'html' // HTML / 自定义标签 <tag>
| 'emphasis' // 强调 *斜体* **粗体**
| 'list' // 列表 - + *
| 'table'; // 表格 | header | content |hasNextChunk 为 true 时,未完成 token 会转成 incomplete-<token>(可用 incompleteMarkdownComponentMap 改名),原文放在 data-raw(encodeURIComponent)。text 不生成占位标签。
FAQ
Components 与 config marked extensions 的区别
config marked extensions(解析扩展)
config 里的 extensions 在 Markdown → HTML 阶段生效:
- 阶段:Markdown 解析
- 作用:识别并转换特殊语法
- 例子:把
[^1]脚注语法变成<footnote>1</footnote> - 场景:扩展 Markdown 语法
ts
const footnoteExtension = {
name: 'footnote',
level: 'inline',
start(src) {
return src.match(/\[\^/)?.index;
},
tokenizer(src) {
const rule = /^\[\^([^\]]+)\]/;
const match = rule.exec(src);
if (match) {
return {
type: 'footnote',
raw: match[0],
text: match[1],
};
}
},
renderer(token) {
return `<footnote>${token.text}</footnote>`;
},
};
// <XMarkdown content="脚注示例[^1]" :config="{ extensions: [footnoteExtension] }" />components(组件替换)
components 在 HTML → VNode 阶段把标签换成 Vue 组件:
- 阶段:渲染
- 作用:替换 HTML / 自定义标签
- 例子:把
<footnote>1</footnote>换成可点击的脚注组件 - 场景:自定义样式与交互
完整示例见 自定义插件。