@blueking/chat-x 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ai-selection/ai-selection.vue.d.ts +2 -2
- package/dist/components/index.d.ts +2 -1
- package/dist/index.css +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp/generated/docs/activity-message.md +428 -0
- package/dist/mcp/generated/docs/ai-image.md +227 -0
- package/dist/mcp/generated/docs/ai-loading.md +129 -0
- package/dist/mcp/generated/docs/ai-selection.md +436 -0
- package/dist/mcp/generated/docs/animation-text.md +199 -0
- package/dist/mcp/generated/docs/assistant-message.md +424 -0
- package/dist/mcp/generated/docs/chat-container.md +402 -0
- package/dist/mcp/generated/docs/chat-input.md +625 -0
- package/dist/mcp/generated/docs/cite-content.md +138 -0
- package/dist/mcp/generated/docs/code-content.md +199 -0
- package/dist/mcp/generated/docs/common-error-content.md +70 -0
- package/dist/mcp/generated/docs/constants.md +216 -0
- package/dist/mcp/generated/docs/content-render.md +238 -0
- package/dist/mcp/generated/docs/delete-tool.md +188 -0
- package/dist/mcp/generated/docs/desc-panel.md +139 -0
- package/dist/mcp/generated/docs/execution-summary.md +126 -0
- package/dist/mcp/generated/docs/file-content.md +300 -0
- package/dist/mcp/generated/docs/file-upload-btn.md +174 -0
- package/dist/mcp/generated/docs/flow-message.md +305 -0
- package/dist/mcp/generated/docs/highlight-keyword.md +144 -0
- package/dist/mcp/generated/docs/image-content.md +178 -0
- package/dist/mcp/generated/docs/image-preview-group.md +181 -0
- package/dist/mcp/generated/docs/image-preview.md +224 -0
- package/dist/mcp/generated/docs/info-message.md +124 -0
- package/dist/mcp/generated/docs/key-value-content.md +124 -0
- package/dist/mcp/generated/docs/latex-content.md +196 -0
- package/dist/mcp/generated/docs/loading-message.md +171 -0
- package/dist/mcp/generated/docs/markdown-content.md +186 -0
- package/dist/mcp/generated/docs/markdown-latex.md +208 -0
- package/dist/mcp/generated/docs/markdown-mermaid.md +250 -0
- package/dist/mcp/generated/docs/mermaid-content.md +185 -0
- package/dist/mcp/generated/docs/message-container.md +534 -0
- package/dist/mcp/generated/docs/message-render.md +329 -0
- package/dist/mcp/generated/docs/message-tools.md +376 -0
- package/dist/mcp/generated/docs/messages.md +472 -0
- package/dist/mcp/generated/docs/overflow-tips.md +209 -0
- package/dist/mcp/generated/docs/reasoning-message.md +233 -0
- package/dist/mcp/generated/docs/reference-content.md +132 -0
- package/dist/mcp/generated/docs/scroll-btn.md +155 -0
- package/dist/mcp/generated/docs/selection-footer.md +75 -0
- package/dist/mcp/generated/docs/shortcut-btn.md +202 -0
- package/dist/mcp/generated/docs/shortcut-btns.md +264 -0
- package/dist/mcp/generated/docs/shortcut-render.md +418 -0
- package/dist/mcp/generated/docs/text-content.md +74 -0
- package/dist/mcp/generated/docs/theme.md +388 -0
- package/dist/mcp/generated/docs/tool-btn.md +254 -0
- package/dist/mcp/generated/docs/tool-message.md +217 -0
- package/dist/mcp/generated/docs/toolcall-render.md +299 -0
- package/dist/mcp/generated/docs/use-animation-text.md +198 -0
- package/dist/mcp/generated/docs/use-clipboard.md +206 -0
- package/dist/mcp/generated/docs/use-command-selection.md +128 -0
- package/dist/mcp/generated/docs/use-container-scroll.md +56 -0
- package/dist/mcp/generated/docs/use-custom-tab.md +122 -0
- package/dist/mcp/generated/docs/use-global-config.md +154 -0
- package/dist/mcp/generated/docs/use-menu-keydown.md +164 -0
- package/dist/mcp/generated/docs/use-message-group.md +175 -0
- package/dist/mcp/generated/docs/use-observer-visible-list.md +189 -0
- package/dist/mcp/generated/docs/use-parent-scrolling.md +46 -0
- package/dist/mcp/generated/docs/user-feedback.md +229 -0
- package/dist/mcp/generated/docs/user-message.md +347 -0
- package/dist/mcp/generated/index.json +1311 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +42 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +43 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/get-component-doc.d.ts +19 -0
- package/dist/mcp/tools/get-component-doc.js +60 -0
- package/dist/mcp/tools/get-component-doc.js.map +1 -0
- package/dist/mcp/tools/list-components.d.ts +35 -0
- package/dist/mcp/tools/list-components.js +147 -0
- package/dist/mcp/tools/list-components.js.map +1 -0
- package/dist/mcp/tools/search-docs.d.ts +14 -0
- package/dist/mcp/tools/search-docs.js +82 -0
- package/dist/mcp/tools/search-docs.js.map +1 -0
- package/dist/mcp/utils/doc-loader.d.ts +35 -0
- package/dist/mcp/utils/doc-loader.js +64 -0
- package/dist/mcp/utils/doc-loader.js.map +1 -0
- package/package.json +5 -7
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
LatexContent 使用 KaTeX 渲染 math_block / math_inline 等 token,支持行内块级混排与流式防抖。 必填 props 为 token 数组;失败时静默降级展示原始 LaTeX 文本。 由 MarkdownContent 在数学插件解析后自动调用。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **markdown-content** — 插件解析 $...$ / $$...$$ 后生成数学 token 并挂载本组件
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
<!-- FULL DOC -->
|
|
11
|
+
|
|
12
|
+
# LatexContent LaTeX 公式渲染
|
|
13
|
+
|
|
14
|
+
> **层级**:原子组件 · **功能域**:内容渲染
|
|
15
|
+
|
|
16
|
+
Markdown Token 层的 LaTeX 公式渲染原子组件,基于 **KaTeX** 实现。被 `MarkdownContent` 在解析到数学公式 token 时自动调用,通常无需手动引入。
|
|
17
|
+
|
|
18
|
+
核心能力:**流式防抖渲染**(throttle 100ms)、**语法自动补全**(`completeLatexContent`)、**渐进式降级重试**(最多 5 次)、**错误静默**(错误文本白色不可见)。
|
|
19
|
+
|
|
20
|
+
## 组件结构与 Token 渲染路径
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
props.token(Token[])
|
|
24
|
+
│
|
|
25
|
+
├─ token.type === 'math_block'(单块且 token.length ≤ 1)
|
|
26
|
+
│ wrapperTag = 'div',wrapperClass = 'block-latex-content'
|
|
27
|
+
│ └─ <div class="block-latex-wrapper">
|
|
28
|
+
│ └─ renderLatexToken(token) → <span class="block-katex">KaTeX HTML</span>
|
|
29
|
+
│
|
|
30
|
+
├─ token.type === 'math_inline'(或混合 token 数组)
|
|
31
|
+
│ wrapperTag = 'span',wrapperClass = 'inline-latex-content'
|
|
32
|
+
│ └─ renderLatexToken(token) → <span class="inline-katex">KaTeX HTML</span>
|
|
33
|
+
│
|
|
34
|
+
├─ token.type === 'inline'(含 children)
|
|
35
|
+
│ └─ renderInlineChildren(token.children)
|
|
36
|
+
│ ├─ math_inline → renderLatexToken(递归)
|
|
37
|
+
│ ├─ text → escapeHtml
|
|
38
|
+
│ ├─ softbreak → '\n'
|
|
39
|
+
│ ├─ hardbreak → '<br>'
|
|
40
|
+
│ ├─ code_inline → '<code>...</code>'
|
|
41
|
+
│ ├─ strong_open/close → '<strong>' / '</strong>'
|
|
42
|
+
│ ├─ em_open/close → '<em>' / '</em>'
|
|
43
|
+
│ ├─ s_open/close → '<s>' / '</s>'
|
|
44
|
+
│ ├─ link_open/close → '<a href="...">...</a>'
|
|
45
|
+
│ ├─ image → '<img src="..." alt="...">'
|
|
46
|
+
│ └─ 未知类型 → escapeHtml(token.content)
|
|
47
|
+
│
|
|
48
|
+
├─ token.type === 'paragraph_open/close' → '<p>' / '</p>'
|
|
49
|
+
└─ token.type === 'text' / 其他 → escapeHtml(token.content)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### displayMode 判断规则
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// renderLatexToken 内部
|
|
56
|
+
const displayMode = token.type === 'math_block' || token.meta?.displayMode === true;
|
|
57
|
+
// math_inline 也可通过 meta.displayMode=true 强制块级渲染
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 基础用法:块级公式
|
|
61
|
+
|
|
62
|
+
```vue
|
|
63
|
+
<template>
|
|
64
|
+
<LatexContent :token="token" />
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<script setup lang="ts">
|
|
68
|
+
import { LatexContent } from '@blueking/chat-x';
|
|
69
|
+
import type { Token } from 'markdown-it';
|
|
70
|
+
|
|
71
|
+
const token: Token[] = [{ type: 'math_block', content: 'E = mc^2' } as Token];
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 行内公式
|
|
76
|
+
|
|
77
|
+
`math_inline` 类型,包装为 `span.inline-latex-content`,嵌入文字流中渲染:
|
|
78
|
+
|
|
79
|
+
```vue
|
|
80
|
+
<template>
|
|
81
|
+
<!-- 行内公式 -->
|
|
82
|
+
<LatexContent :token="[{ type: 'math_inline', content: 'a^2 + b^2 = c^2' }]" />
|
|
83
|
+
</template>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 混合 inline token(文字 + 公式)
|
|
87
|
+
|
|
88
|
+
传入 `inline` token 并带 `children` 时,`renderInlineChildren` 逐一处理文本、公式、标记:
|
|
89
|
+
|
|
90
|
+
## 积分与根号
|
|
91
|
+
|
|
92
|
+
## 矩阵
|
|
93
|
+
|
|
94
|
+
## 对齐环境
|
|
95
|
+
|
|
96
|
+
## 流式渲染防闪烁
|
|
97
|
+
|
|
98
|
+
组件针对流式 Markdown 输入进行了优化:**100ms throttle**(leading + trailing)避免每字符重渲染,**`completeLatexContent`** 在每次渲染前自动补全不完整语法:
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<template>
|
|
102
|
+
<LatexContent :token="streamingTokens" />
|
|
103
|
+
</template>
|
|
104
|
+
|
|
105
|
+
<script setup lang="ts">
|
|
106
|
+
import { ref } from 'vue';
|
|
107
|
+
import { LatexContent } from '@blueking/chat-x';
|
|
108
|
+
|
|
109
|
+
const streamingTokens = ref([{ type: 'math_block', content: '' }]);
|
|
110
|
+
|
|
111
|
+
const simulate = async () => {
|
|
112
|
+
const formula = '\\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}';
|
|
113
|
+
let content = '';
|
|
114
|
+
for (const char of formula) {
|
|
115
|
+
await new Promise(r => setTimeout(r, 50));
|
|
116
|
+
content += char;
|
|
117
|
+
streamingTokens.value = [{ type: 'math_block', content }];
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
</script>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 语法自动补全(completeLatexContent)
|
|
124
|
+
|
|
125
|
+
在每次调用 KaTeX 前,组件先通过 `completeLatexContent` 修复不完整语法,处理顺序为:
|
|
126
|
+
|
|
127
|
+
| 步骤 | 处理内容 | 示例 |
|
|
128
|
+
| ---- | --------------------------------------------------------------------- | --------------------------------------------- |
|
|
129
|
+
| 0 | 不完整 `\begin{env` → 猜测环境名补全 `\begin{env}\end{env}` | `\begin{pma` → `\begin{pmatrix}\end{pmatrix}` |
|
|
130
|
+
| 0.1 | 不完整 `\end{env` → 猜测环境名补全 | `\end{alig` → `\end{aligned}` |
|
|
131
|
+
| 0.2 | 末尾不完整命令 `\begi` → 若匹配已知命令前缀则移除,完整命令则补全参数 | `\frac` → `\frac{}{}` |
|
|
132
|
+
| 1 | 未闭合 `{}` → 补全缺失的 `}` | `\frac{a}{b` → `\frac{a}{b}` |
|
|
133
|
+
| 2 | 未闭合 `[]` → 补全缺失的 `]` | `\sqrt[3` → `\sqrt[3]` |
|
|
134
|
+
| 3 | 双参数命令缺第二个参数 → 追加 `{}` | `\frac{a}` → `\frac{a}{}` |
|
|
135
|
+
| 4 | `\begin{env}` 无对应 `\end{env}` → 追加 `\end{env}` | `\begin{matrix}...` → `...\end{matrix}` |
|
|
136
|
+
|
|
137
|
+
**可猜测的环境名**(`COMMON_ENVS`):`aligned`、`align`、`equation`、`gather`、`matrix`、`pmatrix`、`bmatrix`、`vmatrix`、`cases`、`array`、`split`、`multline`
|
|
138
|
+
|
|
139
|
+
**双参数命令**(`TWO_ARG_COMMANDS`):`frac`、`dfrac`、`tfrac`、`binom`、`cfrac`、`overset`、`underset` 等
|
|
140
|
+
|
|
141
|
+
**单参数命令**(`ONE_ARG_COMMANDS`):`sqrt`、`text`、`mathbf`、`hat`、`vec`、`overline`、`boxed` 等
|
|
142
|
+
|
|
143
|
+
## 渐进式降级重试(tryRenderKatex)
|
|
144
|
+
|
|
145
|
+
补全后仍渲染失败时,最多重试 5 次,每次尝试两种裁剪策略:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
尝试 completeLatexContent(content) → KaTeX 渲染
|
|
149
|
+
失败 →
|
|
150
|
+
策略 1:移除末尾不完整命令(正则 /\\[a-zA-Z]+(\{[^{}]*\})*\s*$/)
|
|
151
|
+
策略 2:移除未闭合 {(正则 /\{[^{}]*$/)
|
|
152
|
+
若仍失败 → 返回 null
|
|
153
|
+
→ 渲染 <span class="katex-loading" style="color: #666; font-style: italic;">原始文本(HTML 转义)</span>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
> **错误静默**:KaTeX 以 `errorColor: '#fff'`(白色)渲染错误文本,错误不可见。若检测到 HTML 中含 `katex-error` 类或 `color:#cc0000`,也视为渲染失败,降级为 `katex-loading` 显示原始文本。
|
|
157
|
+
|
|
158
|
+
## API
|
|
159
|
+
|
|
160
|
+
### Props
|
|
161
|
+
|
|
162
|
+
| 属性名 | 类型 | 必填 | 说明 |
|
|
163
|
+
| ------ | --------- | ---- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
164
|
+
| token | `Token[]` | ✓ | markdown-it Token 数组;支持 `math_block`、`math_inline`、`inline`(含 children)、`paragraph_open/close`、`text` 等类型 |
|
|
165
|
+
|
|
166
|
+
### Token 结构
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// math_block / math_inline
|
|
170
|
+
{
|
|
171
|
+
type: 'math_block' | 'math_inline';
|
|
172
|
+
content: string; // LaTeX 公式字符串
|
|
173
|
+
meta?: { displayMode?: boolean }; // true → 块级渲染(math_inline 可用此强制块级)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// inline(含行内标记 + 公式混排)
|
|
177
|
+
{
|
|
178
|
+
type: 'inline';
|
|
179
|
+
children: Token[]; // 子 token 列表
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 样式说明
|
|
184
|
+
|
|
185
|
+
| 类名 | 标签 | 作用 |
|
|
186
|
+
| ----------------------- | ------ | ------------------------------------------------------------------------------------------- |
|
|
187
|
+
| `.block-latex-content` | `div` | 单一 `math_block` 时的外层,`text-align: center`,`overflow: auto hidden`,`margin: 16px 0` |
|
|
188
|
+
| `.inline-latex-content` | `span` | 混合/行内时的外层,`display: inline`,`vertical-align: baseline` |
|
|
189
|
+
| `.block-latex-wrapper` | `div` | 每个 `math_block` token 的包装,`text-align: center`,`margin: 16px 0` |
|
|
190
|
+
| `.block-katex` | `span` | 块级 KaTeX 输出 |
|
|
191
|
+
| `.inline-katex` | `span` | 行内 KaTeX 输出 |
|
|
192
|
+
| `.katex-loading` | `span` | 渲染失败降级态,斜体灰色显示原始 LaTeX 文本 |
|
|
193
|
+
|
|
194
|
+
## 关联组件
|
|
195
|
+
|
|
196
|
+
- [MarkdownContent](./markdown-content.md) — 数学公式 token 的来源与挂载
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
LoadingMessage 展示等待 AI 响应的加载动画(内部 AiLoading),无必填 Props,默认插槽可自定义「请求中」文案。 典型用法是由 MessageContainer 在末尾为用户消息时自动注入 Loading 组;也可在自定义布局中手动放置。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **message-container** — 在消息列表末尾自动追加 Loading 消息组
|
|
8
|
+
- **message-render** — role 为 loading 时由 MessageRender 渲染
|
|
9
|
+
- **ai-loading** — 内部使用 AiLoading 原子组件
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
<!-- FULL DOC -->
|
|
13
|
+
|
|
14
|
+
# LoadingMessage 加载中消息
|
|
15
|
+
|
|
16
|
+
> **层级**:分子组件 · **功能域**:消息展示
|
|
17
|
+
|
|
18
|
+
加载等待状态组件,展示 AI 正在处理请求时的过渡动画。由旋转渐变环 + 脉冲星形图标(蓝→紫→粉渐变)和"请求中..."文案组成。支持通过默认插槽自定义加载文案。
|
|
19
|
+
|
|
20
|
+
> **提示**:此组件通常**不需要手动使用**,`MessageContainer` 会在满足条件时自动注入。
|
|
21
|
+
|
|
22
|
+
## 渲染效果
|
|
23
|
+
|
|
24
|
+
## 基础用法
|
|
25
|
+
|
|
26
|
+
组件无 Props,直接引入渲染即可:
|
|
27
|
+
|
|
28
|
+
```vue
|
|
29
|
+
<template>
|
|
30
|
+
<LoadingMessage />
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { LoadingMessage } from '@blueking/chat-x';
|
|
35
|
+
</script>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 自定义加载文案
|
|
39
|
+
|
|
40
|
+
通过默认插槽可覆盖默认的"请求中..."文案:
|
|
41
|
+
|
|
42
|
+
```vue
|
|
43
|
+
<template>
|
|
44
|
+
<LoadingMessage>正在思考中,请稍候...</LoadingMessage>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<script setup lang="ts">
|
|
48
|
+
import { LoadingMessage } from '@blueking/chat-x';
|
|
49
|
+
</script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 动画说明
|
|
53
|
+
|
|
54
|
+
`LoadingMessage` 内部使用 `AiLoading` 组件(18px),由两层动画叠加:
|
|
55
|
+
|
|
56
|
+
| 图层 | 动画 | 周期 |
|
|
57
|
+
| ---------- | ----------------------------------- | ---- |
|
|
58
|
+
| 旋转渐变环 | `rotate(0 → 360deg)`,线性 | 0.8s |
|
|
59
|
+
| 脉冲星形 | `scale(0.5 → 1 → 0.5)`,ease-in-out | 0.8s |
|
|
60
|
+
|
|
61
|
+
颜色均使用线性渐变:`#235DFA`(蓝)→ `#8A77EC`(紫)→ `#EB8CEC`(粉)。
|
|
62
|
+
|
|
63
|
+
## 在 MessageContainer 中的自动注入
|
|
64
|
+
|
|
65
|
+
`MessageContainer` 在构建消息分组列表时,检测到**消息列表最后一条为用户消息**(`role === 'user'`)时,自动在末尾追加一个 Loading 消息组:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// MessageContainer 内部逻辑(简化)
|
|
69
|
+
if (messages.at(-1)?.role === MessageRole.User) {
|
|
70
|
+
list.push({
|
|
71
|
+
messages: [
|
|
72
|
+
{
|
|
73
|
+
role: MessageRole.Loading, // 'loading'
|
|
74
|
+
content: '',
|
|
75
|
+
status: MessageStatus.Pending,
|
|
76
|
+
id: 'loading',
|
|
77
|
+
messageId: '',
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
type: MessageRole.Loading,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
当下一条 AI 消息(`role: 'assistant'`)到来后,最后一条不再是用户消息,Loading 组自动消失。
|
|
86
|
+
|
|
87
|
+
**触发示例**:
|
|
88
|
+
|
|
89
|
+
```vue
|
|
90
|
+
<template>
|
|
91
|
+
<MessageContainer
|
|
92
|
+
:messages="messages"
|
|
93
|
+
:message-status="messageStatus"
|
|
94
|
+
:on-agent-action="handleAgentAction"
|
|
95
|
+
/>
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<script setup lang="ts">
|
|
99
|
+
import { ref } from 'vue';
|
|
100
|
+
import { MessageContainer, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
101
|
+
|
|
102
|
+
const messageStatus = ref(MessageStatus.Pending);
|
|
103
|
+
|
|
104
|
+
// 最后一条是 user 消息 → MessageContainer 自动追加 LoadingMessage
|
|
105
|
+
const messages = ref([
|
|
106
|
+
{
|
|
107
|
+
id: '1',
|
|
108
|
+
messageId: '1',
|
|
109
|
+
role: MessageRole.User,
|
|
110
|
+
content: '请帮我写一段 Vue 3 组合式 API 的示例代码',
|
|
111
|
+
status: MessageStatus.Complete,
|
|
112
|
+
},
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
const handleAgentAction = async () => {};
|
|
116
|
+
</script>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 注意事项
|
|
120
|
+
|
|
121
|
+
- **无 Props**:`LoadingMessage` 组件内部没有 `defineProps`,`MessageRender` 向其传入 message 对象的字段均被忽略
|
|
122
|
+
- **默认插槽**:可通过默认插槽自定义加载文案,未传入时显示内置的 "请求中..."
|
|
123
|
+
- **i18n 支持**:默认文案 "请求中..." 通过内置 `t()` 函数处理,英文环境自动显示 "Requesting..."
|
|
124
|
+
- **选择模式**:`MessageContainer` 开启 `enableSelection` 时,Loading 消息组不显示复选框
|
|
125
|
+
- **自动生命周期**:Loading 组随消息列表变化自动插入/移除,无需手动控制
|
|
126
|
+
|
|
127
|
+
## API
|
|
128
|
+
|
|
129
|
+
### Props
|
|
130
|
+
|
|
131
|
+
组件无 Props。
|
|
132
|
+
|
|
133
|
+
> `MessageRender` 渲染 `role: 'loading'` 消息时会传入 message 对象字段,但 `LoadingMessage` 内部无 `defineProps`,所有传入字段均被忽略。
|
|
134
|
+
|
|
135
|
+
### Slots
|
|
136
|
+
|
|
137
|
+
| 插槽名 | 说明 |
|
|
138
|
+
| ------- | ----------------------------------------------- |
|
|
139
|
+
| default | 自定义加载文案,默认内容为 i18n 文案"请求中..." |
|
|
140
|
+
|
|
141
|
+
## 类型定义
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
145
|
+
|
|
146
|
+
// MessageContainer 自动注入的 Loading 消息结构
|
|
147
|
+
type LoadingMessageData = {
|
|
148
|
+
id: 'loading';
|
|
149
|
+
messageId: '';
|
|
150
|
+
role: MessageRole.Loading; // 'loading'
|
|
151
|
+
content: '';
|
|
152
|
+
status: MessageStatus.Pending;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
enum MessageRole {
|
|
156
|
+
Loading = 'loading',
|
|
157
|
+
// ...
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 使用场景
|
|
162
|
+
|
|
163
|
+
- **等待 AI 响应**:用户消息发出后、AI 首个 token 到达前的过渡状态,由 `MessageContainer` 自动管理
|
|
164
|
+
- **手动控制场景**:在自定义聊天布局中手动展示加载态(直接引入即可,无需任何配置)
|
|
165
|
+
- **自定义文案**:通过默认插槽传入自定义加载提示文案,满足不同业务场景的文案需求
|
|
166
|
+
|
|
167
|
+
## 关联组件
|
|
168
|
+
|
|
169
|
+
- [MessageContainer](./message-container.md) — 自动注入加载组
|
|
170
|
+
- [MessageRender](./message-render.md) — loading 角色派发
|
|
171
|
+
- [AiLoading](../atomic/ai-loading.md) — 内部动画组件
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
MarkdownContent 将 Markdown 字符串解析为 token 并渲染,集成代码块、公式、Mermaid 等子渲染器。 核心 props 为 content 与 status;内置流式节流、语法补全与 DOMPurify 安全策略。 通常由 ContentRender、AssistantMessage 等间接使用,无需业务直接挂载。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **code-content** — fence 代码块语法高亮与复制
|
|
8
|
+
- **latex-content** — 数学公式 token 的 KaTeX 渲染
|
|
9
|
+
- **mermaid-content** — mermaid 代码块的图表渲染
|
|
10
|
+
- **content-render** — 上层按类型分发到本组件渲染 Markdown 字符串
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
<!-- FULL DOC -->
|
|
14
|
+
|
|
15
|
+
# MarkdownContent Markdown 内容渲染
|
|
16
|
+
|
|
17
|
+
> **层级**:原子组件 · **功能域**:内容渲染
|
|
18
|
+
|
|
19
|
+
AI 消息内容渲染的核心原子组件,集成代码高亮、LaTeX 公式、Mermaid 图表等能力,内置流式渲染优化(5ms throttle + 语法补全 + 防闪烁)。
|
|
20
|
+
|
|
21
|
+
由 `AssistantMessage`、`ReasoningMessage` 等分子组件内部自动使用,通常不需要手动引入。
|
|
22
|
+
|
|
23
|
+
## 组件结构与渲染流程
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
props.content → completeMarkdownSyntax → md.parse → groupTokens → groupedTokens
|
|
27
|
+
│
|
|
28
|
+
div.markdown-content(contain: layout style)
|
|
29
|
+
│
|
|
30
|
+
status === 'error' → CommonErrorContent(:content)
|
|
31
|
+
│
|
|
32
|
+
else → div.markdown-body(contain: content)
|
|
33
|
+
│
|
|
34
|
+
v-for groupedToken
|
|
35
|
+
│
|
|
36
|
+
┌─────────────┼────────────────────┬───────────────┐
|
|
37
|
+
│ │ │ │
|
|
38
|
+
hasMermaid? hasLatex? hasCode? else
|
|
39
|
+
↓ ↓ ↓ ↓
|
|
40
|
+
MermaidContent LatexContent CodeContent VNodeRenderer
|
|
41
|
+
@mounted @mounted @mounted @vue:mounted
|
|
42
|
+
│
|
|
43
|
+
└──── handleTokenMounted(throttle 100ms)→ containerScroll.toScrollBottom()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Token 分组(groupTokens)
|
|
47
|
+
|
|
48
|
+
`groupTokens` 使用栈将扁平 Token 数组转为分组数组,每组对应一个顶层 DOM 节点(段落、标题、列表、代码块等):
|
|
49
|
+
|
|
50
|
+
- `nesting === 1`(open)→ 入栈,建立新 group;顶层 group 立刻加入结果
|
|
51
|
+
- `nesting === -1`(close)→ 出栈,完成该 group;嵌套 group 合并到父 group
|
|
52
|
+
- `nesting === 0`(自闭合/inline)→ 无栈时独立成组,有栈时追加到当前 group
|
|
53
|
+
|
|
54
|
+
每组第一个 token 的 `attrs` 追加 `class="ai-blueking-markdown-fade-in"`,触发渐显动画。
|
|
55
|
+
|
|
56
|
+
### 子组件优先级
|
|
57
|
+
|
|
58
|
+
对每个 token 组按以下顺序判断:
|
|
59
|
+
|
|
60
|
+
| 优先级 | 检测逻辑 | 使用组件 |
|
|
61
|
+
| ------ | -------------------------------------------------------------------- | ----------------------------------------- |
|
|
62
|
+
| 1 | `fence` token 且 `info === 'mermaid'` | `MermaidContent` |
|
|
63
|
+
| 2 | `math_inline` / `math_block`,或 children 中递归含有(inline token) | `LatexContent` |
|
|
64
|
+
| 3 | `fence`(非 mermaid)或 `code_block` | `CodeContent` |
|
|
65
|
+
| 4 | 其余 | `VNodeRenderer`(HTML 由 DOMPurify 过滤) |
|
|
66
|
+
|
|
67
|
+
## 基础用法
|
|
68
|
+
|
|
69
|
+
```vue
|
|
70
|
+
<template>
|
|
71
|
+
<MarkdownContent
|
|
72
|
+
:content="markdownText"
|
|
73
|
+
:status="MessageStatus.Complete"
|
|
74
|
+
/>
|
|
75
|
+
</template>
|
|
76
|
+
|
|
77
|
+
<script setup lang="ts">
|
|
78
|
+
import { MarkdownContent, MessageStatus } from '@blueking/chat-x';
|
|
79
|
+
|
|
80
|
+
const markdownText = `# 标题\n\n这是一段 **Markdown** 内容。`;
|
|
81
|
+
</script>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 扩展文本格式
|
|
85
|
+
|
|
86
|
+
支持标准 Markdown + 扩展插件:`++下划线++`(markdown-it-ins)、`==高亮==`(markdown-it-mark)、`~下标~`(markdown-it-sub)、`^上标^`(markdown-it-sup):
|
|
87
|
+
|
|
88
|
+
## 列表与任务清单
|
|
89
|
+
|
|
90
|
+
## 代码块
|
|
91
|
+
|
|
92
|
+
代码块由 `CodeContent` 渲染,支持 highlight.js 语法高亮、语言标签、一键复制:
|
|
93
|
+
|
|
94
|
+
## 表格
|
|
95
|
+
|
|
96
|
+
## LaTeX 公式
|
|
97
|
+
|
|
98
|
+
公式由 `LatexContent`(KaTeX)渲染,支持行内 `$...$` 和块级 `$$...$$`:
|
|
99
|
+
|
|
100
|
+
## Mermaid 图表
|
|
101
|
+
|
|
102
|
+
## 错误状态
|
|
103
|
+
|
|
104
|
+
`status === MessageStatus.Error` 时渲染 `CommonErrorContent`,将 `content` 作为错误文本显示:
|
|
105
|
+
|
|
106
|
+
## 流式渲染
|
|
107
|
+
|
|
108
|
+
````vue
|
|
109
|
+
<template>
|
|
110
|
+
<MarkdownContent
|
|
111
|
+
:content="streamingContent"
|
|
112
|
+
:status="isStreaming ? MessageStatus.Streaming : MessageStatus.Complete"
|
|
113
|
+
/>
|
|
114
|
+
</template>
|
|
115
|
+
|
|
116
|
+
<script setup lang="ts">
|
|
117
|
+
import { ref } from 'vue';
|
|
118
|
+
import { MarkdownContent, MessageStatus } from '@blueking/chat-x';
|
|
119
|
+
|
|
120
|
+
const streamingContent = ref('');
|
|
121
|
+
const isStreaming = ref(false);
|
|
122
|
+
|
|
123
|
+
const simulate = async () => {
|
|
124
|
+
const fullText = '## Hello\n\n**流式输出**演示。\n\n```js\nconsole.log(1);\n```';
|
|
125
|
+
isStreaming.value = true;
|
|
126
|
+
for (const char of fullText) {
|
|
127
|
+
await new Promise(r => setTimeout(r, 30));
|
|
128
|
+
streamingContent.value += char;
|
|
129
|
+
}
|
|
130
|
+
isStreaming.value = false;
|
|
131
|
+
};
|
|
132
|
+
</script>
|
|
133
|
+
````
|
|
134
|
+
|
|
135
|
+
### 流式优化机制
|
|
136
|
+
|
|
137
|
+
| 机制 | 实现 | 作用 |
|
|
138
|
+
| ----------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
139
|
+
| 极速节流 | `parseMarkdownContent` throttle **5ms**,leading + trailing | 每 5ms 最多解析一次,兼顾实时性与性能 |
|
|
140
|
+
| Markdown 语法补全 | `completeMarkdownSyntax(content)` | 自动闭合代码块、行内代码、粗斜体、删除线、链接等未完成语法 |
|
|
141
|
+
| LaTeX 防闪烁 | `isIncomplete=true` 且已有渲染结果 → **跳过本次更新** | 正在输入 LaTeX 命令时保持上一帧,避免闪白 |
|
|
142
|
+
| 子组件 throttle | `handleTokenMounted` throttle 100ms | 限制子组件挂载后触发的滚动到底部频率 |
|
|
143
|
+
| CSS contain | `.markdown-content { contain: layout style }`<br>`.markdown-body { contain: content }` | 限制重排/重绘范围,减少流式渲染的布局开销 |
|
|
144
|
+
| 渐显动画 | 每组首 token 追加 `.ai-blueking-markdown-fade-in` | 新内容块淡入,减少视觉跳跃感 |
|
|
145
|
+
|
|
146
|
+
## API
|
|
147
|
+
|
|
148
|
+
### Props
|
|
149
|
+
|
|
150
|
+
| 属性名 | 类型 | 必填 | 说明 |
|
|
151
|
+
| ------- | --------------- | ---- | --------------------------------------------------------- |
|
|
152
|
+
| content | `string` | — | Markdown 文本;为空时清空渲染结果 |
|
|
153
|
+
| status | `MessageStatus` | — | `'error'` 时显示 `CommonErrorContent`,其余状态均正常渲染 |
|
|
154
|
+
|
|
155
|
+
### 内置插件
|
|
156
|
+
|
|
157
|
+
| 插件 | 语法 | 功能 |
|
|
158
|
+
| --------------------------- | ------------------- | -------------------- |
|
|
159
|
+
| `markdown-it-footnote` | `[^1]` | 脚注 |
|
|
160
|
+
| `markdown-it-ins` | `++text++` | 下划线 |
|
|
161
|
+
| `markdown-it-mark` | `==text==` | 高亮 |
|
|
162
|
+
| `markdown-it-sub` | `~text~` | 下标 |
|
|
163
|
+
| `markdown-it-sup` | `^text^` | 上标 |
|
|
164
|
+
| `markdown-it-task-checkbox` | `- [x]` | 任务列表 |
|
|
165
|
+
| `markdownItMermaid` | ` ```mermaid ` | Mermaid 图表 token |
|
|
166
|
+
| `markdownItLatex` | `$...$` / `$$...$$` | KaTeX 数学公式 token |
|
|
167
|
+
|
|
168
|
+
### 安全性
|
|
169
|
+
|
|
170
|
+
`VNodeRenderer` 渲染的 HTML 统一经过 DOMPurify 过滤,并额外允许 KaTeX 所需标签:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const domPurifyConfig = {
|
|
174
|
+
ADD_TAGS: ['semantics', 'mrow', 'mi', 'mo', 'mn', 'msup', 'msub', 'mfrac', 'mtext', 'annotation'],
|
|
175
|
+
ADD_ATTR: ['xmlns', 'mathvariant', 'encoding', 'style'],
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
> `CodeContent`、`MermaidContent`、`LatexContent` 各自内部处理安全性(KaTeX `errorColor`、highlight.js 转义等),不经过 DOMPurify。
|
|
180
|
+
|
|
181
|
+
## 关联组件
|
|
182
|
+
|
|
183
|
+
- [CodeContent](./code-content.md) — 代码 fence 高亮
|
|
184
|
+
- [LatexContent](./latex-content.md) — 公式渲染
|
|
185
|
+
- [MermaidContent](./mermaid-content.md) — Mermaid 图表
|
|
186
|
+
- [ContentRender](../molecular/content-render.md) — 内容类型分发入口
|