@blueking/chat-x 0.0.50 → 0.0.51-beta.2

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.
Files changed (147) hide show
  1. package/dist/ag-ui/types/contents.d.ts +2 -0
  2. package/dist/ag-ui/types/messages.d.ts +5 -0
  3. package/dist/common/constants.d.ts +1 -1
  4. package/dist/components/ai-buttons/file-upload-btn/file-upload-btn.vue.d.ts +0 -2
  5. package/dist/components/chat-content/file-content/file-content.vue.d.ts +5 -2
  6. package/dist/components/chat-content/file-content/upload-file-item.vue.d.ts +12 -0
  7. package/dist/components/chat-content/file-content/upload-image-item.vue.d.ts +21 -0
  8. package/dist/components/chat-input/ai-slash-editor/ai-slash-editor.vue.d.ts +1 -1
  9. package/dist/components/chat-input/build-default-placeholder.d.ts +7 -0
  10. package/dist/components/chat-input/chat-input.vue.d.ts +1 -1
  11. package/dist/components/chat-message/message-container/message-container.vue.d.ts +1 -0
  12. package/dist/components/chat-message/message-render/message-render.vue.d.ts +2 -0
  13. package/dist/components/chat-message/user-message/user-message.vue.d.ts +3 -1
  14. package/dist/components/index.d.ts +2 -1
  15. package/dist/components/message-tools/message-time/format-message-time.d.ts +8 -0
  16. package/dist/components/message-tools/message-time/message-time.vue.d.ts +8 -0
  17. package/dist/components/message-tools/message-tools.vue.d.ts +11 -1
  18. package/dist/composables/use-custom-tab.d.ts +5 -3
  19. package/dist/composables/use-global-config.d.ts +3 -0
  20. package/dist/composables/use-message-group.d.ts +150 -72
  21. package/dist/icons/execution.d.ts +6 -0
  22. package/dist/icons/tools.d.ts +3 -0
  23. package/dist/index.css +1 -1
  24. package/dist/index.js +3124 -2837
  25. package/dist/index.js.map +1 -1
  26. package/dist/lang/lang.d.ts +8 -7
  27. package/dist/mcp/generated/docs/ai-slash-input.md +2 -0
  28. package/dist/mcp/generated/docs/assistant-message.md +9 -7
  29. package/dist/mcp/generated/docs/chat-container.md +38 -32
  30. package/dist/mcp/generated/docs/chat-input.md +18 -12
  31. package/dist/mcp/generated/docs/cite-content.md +3 -3
  32. package/dist/mcp/generated/docs/desc-panel.md +32 -10
  33. package/dist/mcp/generated/docs/execution-summary.md +3 -3
  34. package/dist/mcp/generated/docs/file-artifact-panel.md +6 -4
  35. package/dist/mcp/generated/docs/file-content.md +89 -73
  36. package/dist/mcp/generated/docs/file-upload-btn.md +16 -18
  37. package/dist/mcp/generated/docs/message-container.md +3 -0
  38. package/dist/mcp/generated/docs/message-render.md +2 -1
  39. package/dist/mcp/generated/docs/message-time.md +180 -0
  40. package/dist/mcp/generated/docs/message-tools.md +47 -12
  41. package/dist/mcp/generated/docs/messages.md +9 -0
  42. package/dist/mcp/generated/docs/toolcall-render.md +82 -43
  43. package/dist/mcp/generated/docs/use-artifact-preview.md +19 -17
  44. package/dist/mcp/generated/docs/use-custom-tab.md +12 -8
  45. package/dist/mcp/generated/docs/use-global-config.md +15 -5
  46. package/dist/mcp/generated/docs/user-message.md +9 -0
  47. package/dist/mcp/generated/docs/user-question-card.md +2 -0
  48. package/dist/mcp/generated/index.json +46 -6
  49. package/dist/types/input.d.ts +6 -0
  50. package/dist/utils/file.d.ts +7 -1
  51. package/dist/utils/index.d.ts +2 -0
  52. package/dist/utils/merge-tools-by-id.d.ts +6 -0
  53. package/dist/utils/upload-file.d.ts +35 -0
  54. package/package.json +3 -2
  55. package/skills/blueking-chat-x/SKILL.md +139 -0
  56. package/skills/blueking-chat-x/references/_index.md +131 -0
  57. package/skills/blueking-chat-x/references/components/activity-layout.md +134 -0
  58. package/skills/blueking-chat-x/references/components/activity-message.md +486 -0
  59. package/skills/blueking-chat-x/references/components/ai-image.md +230 -0
  60. package/skills/blueking-chat-x/references/components/ai-loading.md +131 -0
  61. package/skills/blueking-chat-x/references/components/ai-prompt-list.md +44 -0
  62. package/skills/blueking-chat-x/references/components/ai-selection.md +439 -0
  63. package/skills/blueking-chat-x/references/components/ai-skill-list.md +73 -0
  64. package/skills/blueking-chat-x/references/components/ai-slash-editor.md +43 -0
  65. package/skills/blueking-chat-x/references/components/ai-slash-input.md +56 -0
  66. package/skills/blueking-chat-x/references/components/ai-slash-menu.md +42 -0
  67. package/skills/blueking-chat-x/references/components/animation-text.md +202 -0
  68. package/skills/blueking-chat-x/references/components/assistant-message.md +498 -0
  69. package/skills/blueking-chat-x/references/components/chat-container.md +869 -0
  70. package/skills/blueking-chat-x/references/components/chat-input.md +769 -0
  71. package/skills/blueking-chat-x/references/components/cite-content.md +142 -0
  72. package/skills/blueking-chat-x/references/components/code-content.md +211 -0
  73. package/skills/blueking-chat-x/references/components/common-error-content.md +73 -0
  74. package/skills/blueking-chat-x/references/components/content-render.md +233 -0
  75. package/skills/blueking-chat-x/references/components/delete-tool.md +191 -0
  76. package/skills/blueking-chat-x/references/components/desc-panel.md +162 -0
  77. package/skills/blueking-chat-x/references/components/detail-section.md +91 -0
  78. package/skills/blueking-chat-x/references/components/execution-summary.md +128 -0
  79. package/skills/blueking-chat-x/references/components/file-artifact-panel.md +289 -0
  80. package/skills/blueking-chat-x/references/components/file-content.md +319 -0
  81. package/skills/blueking-chat-x/references/components/file-icon.md +109 -0
  82. package/skills/blueking-chat-x/references/components/file-upload-btn.md +159 -0
  83. package/skills/blueking-chat-x/references/components/flow-agent-content.md +264 -0
  84. package/skills/blueking-chat-x/references/components/flow-agent-node-detail.md +236 -0
  85. package/skills/blueking-chat-x/references/components/highlight-keyword.md +146 -0
  86. package/skills/blueking-chat-x/references/components/image-content.md +182 -0
  87. package/skills/blueking-chat-x/references/components/image-preview-group.md +184 -0
  88. package/skills/blueking-chat-x/references/components/image-preview.md +226 -0
  89. package/skills/blueking-chat-x/references/components/info-message.md +144 -0
  90. package/skills/blueking-chat-x/references/components/input-attachment.md +49 -0
  91. package/skills/blueking-chat-x/references/components/input-info-alert.md +42 -0
  92. package/skills/blueking-chat-x/references/components/interrupt-message.md +212 -0
  93. package/skills/blueking-chat-x/references/components/key-value-content.md +128 -0
  94. package/skills/blueking-chat-x/references/components/knowledge-rag-content.md +122 -0
  95. package/skills/blueking-chat-x/references/components/latex-content.md +200 -0
  96. package/skills/blueking-chat-x/references/components/loading-message.md +192 -0
  97. package/skills/blueking-chat-x/references/components/markdown-content.md +232 -0
  98. package/skills/blueking-chat-x/references/components/mermaid-content.md +189 -0
  99. package/skills/blueking-chat-x/references/components/message-container.md +645 -0
  100. package/skills/blueking-chat-x/references/components/message-loading.md +118 -0
  101. package/skills/blueking-chat-x/references/components/message-render.md +327 -0
  102. package/skills/blueking-chat-x/references/components/message-time.md +177 -0
  103. package/skills/blueking-chat-x/references/components/message-tools.md +416 -0
  104. package/skills/blueking-chat-x/references/components/model-selector.md +155 -0
  105. package/skills/blueking-chat-x/references/components/preview-toolbar.md +42 -0
  106. package/skills/blueking-chat-x/references/components/questions-container.md +85 -0
  107. package/skills/blueking-chat-x/references/components/reasoning-message.md +232 -0
  108. package/skills/blueking-chat-x/references/components/reference-content.md +135 -0
  109. package/skills/blueking-chat-x/references/components/reference-doc-content.md +109 -0
  110. package/skills/blueking-chat-x/references/components/scroll-btn.md +159 -0
  111. package/skills/blueking-chat-x/references/components/selection-footer.md +78 -0
  112. package/skills/blueking-chat-x/references/components/selection-question.md +88 -0
  113. package/skills/blueking-chat-x/references/components/shortcut-btn.md +204 -0
  114. package/skills/blueking-chat-x/references/components/shortcut-btns.md +266 -0
  115. package/skills/blueking-chat-x/references/components/shortcut-render.md +424 -0
  116. package/skills/blueking-chat-x/references/components/simple-table.md +101 -0
  117. package/skills/blueking-chat-x/references/components/text-content.md +77 -0
  118. package/skills/blueking-chat-x/references/components/tool-approval-card.md +183 -0
  119. package/skills/blueking-chat-x/references/components/tool-btn.md +317 -0
  120. package/skills/blueking-chat-x/references/components/tool-message.md +235 -0
  121. package/skills/blueking-chat-x/references/components/toolcall-render.md +348 -0
  122. package/skills/blueking-chat-x/references/components/user-feedback.md +233 -0
  123. package/skills/blueking-chat-x/references/components/user-message.md +424 -0
  124. package/skills/blueking-chat-x/references/components/user-question-answered-card.md +104 -0
  125. package/skills/blueking-chat-x/references/components/user-question-card.md +231 -0
  126. package/skills/blueking-chat-x/references/components/user-question-choice.md +105 -0
  127. package/skills/blueking-chat-x/references/components/user-question-option.md +42 -0
  128. package/skills/blueking-chat-x/references/components/vnode-renderer.md +122 -0
  129. package/skills/blueking-chat-x/references/composables/use-animation-text.md +196 -0
  130. package/skills/blueking-chat-x/references/composables/use-artifact-preview.md +231 -0
  131. package/skills/blueking-chat-x/references/composables/use-clipboard.md +203 -0
  132. package/skills/blueking-chat-x/references/composables/use-command-selection.md +150 -0
  133. package/skills/blueking-chat-x/references/composables/use-container-scroll.md +57 -0
  134. package/skills/blueking-chat-x/references/composables/use-custom-tab.md +158 -0
  135. package/skills/blueking-chat-x/references/composables/use-flow-node-actions.md +157 -0
  136. package/skills/blueking-chat-x/references/composables/use-full-screen.md +112 -0
  137. package/skills/blueking-chat-x/references/composables/use-global-config.md +148 -0
  138. package/skills/blueking-chat-x/references/composables/use-menu-keydown.md +163 -0
  139. package/skills/blueking-chat-x/references/composables/use-message-group.md +247 -0
  140. package/skills/blueking-chat-x/references/composables/use-observer-visible-list.md +188 -0
  141. package/skills/blueking-chat-x/references/composables/use-parent-scrolling.md +46 -0
  142. package/skills/blueking-chat-x/references/theme/theme.md +431 -0
  143. package/skills/blueking-chat-x/references/types/constants.md +307 -0
  144. package/skills/blueking-chat-x/references/types/interrupt.md +379 -0
  145. package/skills/blueking-chat-x/references/types/messages.md +553 -0
  146. package/skills/blueking-chat-x/references/types/schema.md +91 -0
  147. package/skills/blueking-chat-x/scripts/generate-references.mjs +314 -0
@@ -0,0 +1,192 @@
1
+ # LoadingMessage 加载消息
2
+
3
+ > 能力域:消息系统 | 导入:`import { LoadingMessage } from '@blueking/chat-x'` | since 0.0.20
4
+
5
+ 消息列表中的加载占位,默认使用 AiLoading,也支持默认插槽覆盖。 源码位置:src/components/chat-message/loading-message/loading-message.vue。
6
+
7
+ **关联**:message-container(在消息列表末尾自动追加 Loading 消息组)、message-render(role 为 loading 时由 MessageRender 渲染)、ai-loading(内部使用 AiLoading 基础组件)
8
+
9
+ ---
10
+
11
+ # LoadingMessage 加载中消息
12
+
13
+ ## 源码事实
14
+
15
+ - **源码位置**:`src/components/chat-message/loading-message/loading-message.vue`
16
+ - **能力域**:消息系统
17
+ - **能力说明**:消息列表中的加载占位,默认使用 AiLoading,也支持默认插槽覆盖。
18
+
19
+ > **导出说明**:`LoadingMessage` **未**从包入口导出。消费方经 `MessageRender`(`role: 'loading'`)或由 `MessageContainer` 自动注入。下文 `LoadingMessageComp` 为文档站内部示例。
20
+
21
+ 加载等待状态组件:`AiLoading`(18px)+ 默认文案「请求中...」。可通过默认插槽自定义文案。
22
+
23
+ > **提示**:通常**不需要手动使用**,`MessageContainer` / `useMessageGroup` 会在满足条件时自动注入。
24
+
25
+ ## 渲染效果
26
+
27
+ ## 基础用法
28
+
29
+ 组件无 Props。文档站内部示例:
30
+
31
+ ```vue
32
+ <template>
33
+ <LoadingMessageComp />
34
+ </template>
35
+ ```
36
+
37
+ 消费方经 `MessageRender`:
38
+
39
+ ```vue
40
+ <template>
41
+ <MessageRender
42
+ :message="{
43
+ id: 'loading',
44
+ messageId: '',
45
+ role: MessageRole.Loading,
46
+ content: '',
47
+ status: MessageStatus.Pending,
48
+ }"
49
+ />
50
+ </template>
51
+
52
+ <script setup lang="ts">
53
+ import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
54
+ </script>
55
+ ```
56
+
57
+ ## 自定义加载文案
58
+
59
+ 通过默认插槽覆盖「请求中...」:
60
+
61
+ ```vue
62
+ <template>
63
+ <!-- 文档站内部示例 -->
64
+ <LoadingMessageComp>正在思考中,请稍候...</LoadingMessageComp>
65
+ </template>
66
+ ```
67
+
68
+ ## 动画说明
69
+
70
+ `LoadingMessage` 内部使用 `AiLoading` 组件(18px),由两层动画叠加:
71
+
72
+ | 图层 | 动画 | 周期 |
73
+ | ---------- | ----------------------------------- | ---- |
74
+ | 旋转渐变环 | `rotate(0 → 360deg)`,线性 | 0.8s |
75
+ | 脉冲星形 | `scale(0.5 → 1 → 0.5)`,ease-in-out | 0.8s |
76
+
77
+ 颜色均使用线性渐变:`#235DFA`(蓝)→ `#8A77EC`(紫)→ `#EB8CEC`(粉)。
78
+
79
+ ## 在 MessageContainer 中的自动注入
80
+
81
+ `useMessageGroup` 构建分组时,若**最后一条为用户消息**且 **`renderMode !== RenderMode.Share`**,自动在末尾追加 Loading 组:
82
+
83
+ ```typescript
84
+ // use-message-group.ts(简化)
85
+ const shouldAppendLoading =
86
+ messages.at(-1)?.role === MessageRole.User && renderMode !== RenderMode.Share;
87
+
88
+ if (shouldAppendLoading) {
89
+ list.push({
90
+ messages: [
91
+ {
92
+ role: MessageRole.Loading,
93
+ content: '',
94
+ status: MessageStatus.Pending,
95
+ id: 'loading',
96
+ messageId: '',
97
+ },
98
+ ],
99
+ type: MessageRole.Loading,
100
+ });
101
+ }
102
+ ```
103
+
104
+ - 下一条 AI 消息到来后,末尾不再是 user,Loading 组自动消失
105
+ - **分享预览**(`renderMode === RenderMode.Share`)**不会**注入 Loading,避免分享页出现「请求中」占位
106
+
107
+ **触发示例**:
108
+
109
+ ```vue
110
+ <template>
111
+ <MessageContainer
112
+ :messages="messages"
113
+ :message-status="messageStatus"
114
+ :on-agent-action="handleAgentAction"
115
+ />
116
+ </template>
117
+
118
+ <script setup lang="ts">
119
+ import { ref } from 'vue';
120
+ import { MessageContainer, MessageRole, MessageStatus } from '@blueking/chat-x';
121
+
122
+ const messageStatus = ref(MessageStatus.Pending);
123
+
124
+ // 最后一条是 user 消息 → MessageContainer 自动追加 LoadingMessage
125
+ const messages = ref([
126
+ {
127
+ id: '1',
128
+ messageId: '1',
129
+ role: MessageRole.User,
130
+ content: '请帮我写一段 Vue 3 组合式 API 的示例代码',
131
+ status: MessageStatus.Complete,
132
+ },
133
+ ]);
134
+
135
+ const handleAgentAction = async () => {};
136
+ </script>
137
+ ```
138
+
139
+ ## 注意事项
140
+
141
+ - **无 Props**:`LoadingMessage` 组件内部没有 `defineProps`,`MessageRender` 向其传入 message 对象的字段均被忽略
142
+ - **默认插槽**:可通过默认插槽自定义加载文案,未传入时显示内置的 "请求中..."
143
+ - **i18n 支持**:默认文案 "请求中..." 通过内置 `t()` 函数处理,英文环境自动显示 "Requesting..."
144
+ - **选择模式**:`MessageContainer` 开启 `enableSelection` 时,Loading 消息组不显示复选框
145
+ - **分享模式**:`renderMode === RenderMode.Share` 时不自动注入 Loading
146
+ - **自动生命周期**:Loading 组随消息列表变化自动插入/移除,无需手动控制
147
+
148
+ ## API
149
+
150
+ ### Props
151
+
152
+ 组件无 Props。
153
+
154
+ > `MessageRender` 渲染 `role: 'loading'` 消息时会传入 message 对象字段,但 `LoadingMessage` 内部无 `defineProps`,所有传入字段均被忽略。
155
+
156
+ ### Slots
157
+
158
+ | 插槽名 | 说明 |
159
+ | ------- | ----------------------------------------------- |
160
+ | default | 自定义加载文案,默认内容为 i18n 文案"请求中..." |
161
+
162
+ ## 类型定义
163
+
164
+ ```typescript
165
+ import { MessageRole, MessageStatus } from '@blueking/chat-x';
166
+
167
+ // MessageContainer 自动注入的 Loading 消息结构
168
+ type LoadingMessageData = {
169
+ id: 'loading';
170
+ messageId: '';
171
+ role: MessageRole.Loading; // 'loading'
172
+ content: '';
173
+ status: MessageStatus.Pending;
174
+ };
175
+
176
+ enum MessageRole {
177
+ Loading = 'loading',
178
+ // ...
179
+ }
180
+ ```
181
+
182
+ ## 使用场景
183
+
184
+ - **等待 AI 响应**:用户消息发出后、AI 首个 token 到达前的过渡状态,由 `MessageContainer` 自动管理
185
+ - **手动控制场景**:在自定义聊天布局中手动展示加载态(直接引入即可,无需任何配置)
186
+ - **自定义文案**:通过默认插槽传入自定义加载提示文案,满足不同业务场景的文案需求
187
+
188
+ ## 关联组件
189
+
190
+ - [MessageContainer](/components/setup/message-container) — 自动注入加载组
191
+ - [MessageRender](/components/message/message-render) — loading 角色派发
192
+ - [AiLoading](/components/helper/ai-loading) — 内部动画组件
@@ -0,0 +1,232 @@
1
+ # MarkdownContent Markdown 内容渲染
2
+
3
+ > 能力域:内容渲染 | 导入:`import { MarkdownContent } from '@blueking/chat-x'` | since 1.0.0
4
+
5
+ Markdown 主渲染器,集成代码块、公式、错误降级和 codeHeader 插槽。 源码位置:src/components/chat-content/markdown-content/markdown-content.vue。
6
+
7
+ **关联**:code-content(fence 代码块语法高亮与复制)、latex-content(数学公式 token 的 KaTeX 渲染)、mermaid-content(mermaid 代码块的图表渲染)、content-render(上层按类型分发到本组件渲染 Markdown 字符串)
8
+
9
+ ---
10
+
11
+ # MarkdownContent Markdown 内容渲染
12
+ ## 源码事实
13
+
14
+ - **源码位置**:`src/components/chat-content/markdown-content/markdown-content.vue`
15
+ - **能力域**:内容渲染
16
+ - **能力说明**:Markdown 主渲染器,集成代码块、公式、错误降级和 codeHeader 插槽。
17
+
18
+ > **能力域**:内容渲染
19
+
20
+ AI 消息内容渲染的核心基础组件,集成代码高亮、LaTeX 公式、Mermaid 图表等能力,内置流式渲染优化(5ms throttle + 语法补全 + 防闪烁)。
21
+
22
+ 由 `AssistantMessage`、`ReasoningMessage` 等组合组件内部自动使用,通常不需要手动引入。
23
+
24
+ ## 组件结构与渲染流程
25
+
26
+ ```
27
+ props.content → completeMarkdownSyntax → md.parse → groupTokens → groupedTokens
28
+
29
+ div.ai-markdown-content(contain: layout style)
30
+
31
+ status === 'error' → CommonErrorContent(:content)
32
+
33
+ else → div.ai-markdown-body[data-theme](contain: content)
34
+
35
+ v-for groupedToken
36
+
37
+ ┌─────────────┼────────────────────┬───────────────┐
38
+ │ │ │ │
39
+ hasMermaid? hasLatex? hasCode? else
40
+ ↓ ↓ ↓ ↓
41
+ MermaidContent LatexContent CodeContent VNodeRenderer
42
+ @mounted @mounted @mounted @vue:mounted
43
+
44
+ └──── handleTokenMounted(throttle 100ms)→ containerScroll.toScrollBottom()
45
+ ```
46
+
47
+ `VNodeRenderer` 的 `options` 中包含与当前 `MarkdownIt` 实例一致的 `mditOptions`(即 `md.options`),以便 `tokensToVNodes` 调用 `renderer.rules` 时第三参与 markdown-it 原生规则签名一致。
48
+
49
+ ### Token 分组(groupTokens)
50
+
51
+ `groupTokens` 使用栈将扁平 Token 数组转为分组数组,每组对应一个顶层 DOM 节点(段落、标题、列表、代码块等):
52
+
53
+ - `nesting === 1`(open)→ 入栈,建立新 group;顶层 group 立刻加入结果
54
+ - `nesting === -1`(close)→ 出栈,完成该 group;嵌套 group 合并到父 group
55
+ - `nesting === 0`(自闭合/inline)→ 无栈时独立成组,有栈时追加到当前 group
56
+
57
+ 每组第一个 token 的 `attrs` 追加 `class="ai-blueking-markdown-fade-in"`,触发渐显动画。
58
+
59
+ ### 子组件优先级
60
+
61
+ 对每个 token 组按以下顺序判断:
62
+
63
+ | 优先级 | 检测逻辑 | 使用组件 |
64
+ | ------ | -------------------------------------------------------------------- | ----------------------------------------- |
65
+ | 1 | `fence` token 且 `info === 'mermaid'` | `MermaidContent` |
66
+ | 2 | `math_inline` / `math_block`,或 children 中递归含有(inline token) | `LatexContent` |
67
+ | 3 | `fence`(非 mermaid)或 `code_block` | `CodeContent` |
68
+ | 4 | 其余 | `VNodeRenderer`(HTML 由 DOMPurify 过滤) |
69
+
70
+ ## 基础用法
71
+
72
+ ```vue
73
+ <template>
74
+ <MarkdownContent
75
+ :content="markdownText"
76
+ :status="MessageStatus.Complete"
77
+ />
78
+ </template>
79
+
80
+ <script setup lang="ts">
81
+ import { MarkdownContent, MessageStatus } from '@blueking/chat-x';
82
+
83
+ const markdownText = `# 标题\n\n这是一段 **Markdown** 内容。`;
84
+ </script>
85
+ ```
86
+
87
+ ## 扩展文本格式
88
+
89
+ 支持标准 Markdown + 扩展插件:`++下划线++`(markdown-it-ins)、`==高亮==`(markdown-it-mark)、`~下标~`(markdown-it-sub)、`^上标^`(markdown-it-sup):
90
+
91
+ ## 列表与任务清单
92
+
93
+ ## 代码块
94
+
95
+ 代码块由 `CodeContent` 渲染,支持 highlight.js 语法高亮、语言标签、一键复制。语法高亮主题样式由 `CodeContent` 侧引入(`github-dark`),`MarkdownContent` **不再**全局引入 `highlight.js` 主题 CSS,避免与代码块组件重复加载、并保持与消息区样式一致。
96
+
97
+ ## 表格
98
+
99
+ ## 对齐容器(markdown-it-container)
100
+
101
+ 支持 `::: hljs-left` / `::: hljs-center` / `::: hljs-right` 自定义容器,内容渲染在带对应 class 的块级容器中,由内置样式控制 `text-align`:
102
+
103
+ ## LaTeX 公式
104
+
105
+ 公式由 `LatexContent`(KaTeX)渲染,支持行内 `$...$` 和块级 `$$...$$`:
106
+
107
+ ## Mermaid 图表
108
+
109
+ ## 错误状态
110
+
111
+ `status === MessageStatus.Error` 时渲染 `CommonErrorContent`,将 `content` 作为错误文本显示:
112
+
113
+ ## 流式渲染
114
+
115
+ ````vue
116
+ <template>
117
+ <MarkdownContent
118
+ :content="streamingContent"
119
+ :status="isStreaming ? MessageStatus.Streaming : MessageStatus.Complete"
120
+ />
121
+ </template>
122
+
123
+ <script setup lang="ts">
124
+ import { ref } from 'vue';
125
+ import { MarkdownContent, MessageStatus } from '@blueking/chat-x';
126
+
127
+ const streamingContent = ref('');
128
+ const isStreaming = ref(false);
129
+
130
+ const simulate = async () => {
131
+ const fullText = '## Hello\n\n**流式输出**演示。\n\n```js\nconsole.log(1);\n```';
132
+ isStreaming.value = true;
133
+ for (const char of fullText) {
134
+ await new Promise(r => setTimeout(r, 30));
135
+ streamingContent.value += char;
136
+ }
137
+ isStreaming.value = false;
138
+ };
139
+ </script>
140
+ ````
141
+
142
+ ### 流式优化机制
143
+
144
+ | 机制 | 实现 | 作用 |
145
+ | ----------------- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
146
+ | 极速节流 | `parseMarkdownContent` throttle **5ms**,leading + trailing | 每 5ms 最多解析一次,兼顾实时性与性能 |
147
+ | Markdown 语法补全 | `completeMarkdownSyntax(content)` | 自动闭合代码块、行内代码、粗斜体、删除线、链接等未完成语法 |
148
+ | LaTeX 防闪烁 | `isIncomplete=true` 且已有渲染结果 → **跳过本次更新** | 正在输入 LaTeX 命令时保持上一帧,避免闪白 |
149
+ | 子组件 throttle | `handleTokenMounted` throttle 100ms | 限制子组件挂载后触发的滚动到底部频率 |
150
+ | CSS contain | `.ai-markdown-content { contain: layout style }`<br>`.ai-markdown-body { contain: content }` | 限制重排/重绘范围,减少流式渲染的布局开销 |
151
+ | 渐显动画 | 每组首 token 追加 `.ai-blueking-markdown-fade-in` | 新内容块淡入,减少视觉跳跃感 |
152
+
153
+ ## 主题支持
154
+
155
+ 组件通过 `data-theme` 属性和本地 `markdown-content.css`(由 GitHub Markdown 样式 vendoring 而来,类前缀为 `ai-markdown-body`)控制主题,默认为 `light`,避免受宿主页面 `@media (prefers-color-scheme)` 影响。
156
+
157
+ - **Light 模式**(默认):`.ai-markdown-body[data-theme="light"]`,light 变量 + `color-scheme: light`
158
+ - **Dark 模式**:`.ai-markdown-body[data-theme="dark"]`,dark 变量 + `color-scheme: dark`
159
+
160
+ > 外层包裹类名为 `.ai-markdown-content`,内层正文区为 `.ai-markdown-body`,避免与宿主或其他库的 `.markdown-body` 全局样式冲突。
161
+
162
+ ## API
163
+
164
+ ### Props
165
+
166
+ | 属性名 | 类型 | 必填 | 说明 |
167
+ | ------- | --------------- | ---- | --------------------------------------------------------- |
168
+ | content | `string` | — | Markdown 文本;为空时清空渲染结果 |
169
+ | status | `MessageStatus` | — | `'error'` 时显示 `CommonErrorContent`,其余状态均正常渲染 |
170
+
171
+ ### Slots
172
+
173
+ | 插槽名 | 参数 | 说明 |
174
+ | ---------- | -------------------------------------- | --------------------------------------------------------------------------------------- |
175
+ | codeHeader | `{ language: string; token: Token[] }` | 代码块头部自定义操作区域,透传给 CodeContent 的 header 插槽,可添加"插入"、"应用"等按钮 |
176
+
177
+ ### 内置插件
178
+
179
+ | 插件 | 语法 | 功能 |
180
+ | --------------------------- | ------------------- | -------------------- |
181
+ | `markdownItBkInlineStyle` | 见下文「蓝鲸行内样式」 | 安全行内颜色/字号/粗斜体(非 HTML) |
182
+ | `markdown-it-footnote` | `[^1]` | 脚注 |
183
+ | `markdown-it-ins` | `++text++` | 下划线 |
184
+ | `markdown-it-mark` | `==text==` | 高亮 |
185
+ | `markdown-it-sub` | `~text~` | 下标 |
186
+ | `markdown-it-sup` | `^text^` | 上标 |
187
+ | `markdown-it-task-checkbox` | `- [x]` | 任务列表 |
188
+ | `markdownItMermaid` | ` ```mermaid ` | Mermaid 图表 token |
189
+ | `markdownItLatex` | `$...$` / `$$...$$` | KaTeX 数学公式 token |
190
+ | `markdownItContainer` | `::: hljs-left` 等 | 自定义对齐容器(class 与 highlight.js 命名对齐) |
191
+
192
+ ### 蓝鲸行内样式(`markdownItBkInlineStyle`)
193
+
194
+ 不开启 `html: true`,由专用语法生成带白名单 `style` 的 `<span class="bk-md-inline-style">`。
195
+
196
+ **语法**:`::bk{` *属性* `}` *正文* `:/bk::`
197
+
198
+ - 属性写在 `{}` 内,使用 `;` 分隔;每项为 `键=值` 或 `键:值`。
199
+ - 正文支持行内 Markdown(如 `**粗体**`)。
200
+ - 结束标记必须为字面量 `:/bk::`,请勿在正文中出现该序列。
201
+
202
+ **支持的键**:`color` / `c`、`background-color`、`font-size`、`bold`、`italic`(详见 `plugins/markdown-bk-inline-style.ts` 内注释)。
203
+
204
+ **示例**:
205
+
206
+ ```markdown
207
+ ::bk{color:#c00;font-size:18px}**重要**:/bk::
208
+ ::bk{background-color:yellow}高亮:/bk::
209
+ ::bk{bold;italic}强调:/bk::
210
+ ```
211
+
212
+ ### 安全性
213
+
214
+ `MarkdownIt` **不**开启 `html: true`,用户无法插入任意 HTML 标签;行内彩色/字号等请使用上文「蓝鲸行内样式」扩展。
215
+
216
+ `VNodeRenderer` 渲染的 HTML 统一经过 DOMPurify 过滤,并额外允许 KaTeX 所需标签:
217
+
218
+ ```typescript
219
+ const domPurifyConfig = {
220
+ ADD_TAGS: ['semantics', 'mrow', 'mi', 'mo', 'mn', 'msup', 'msub', 'mfrac', 'mtext', 'annotation'],
221
+ ADD_ATTR: ['xmlns', 'mathvariant', 'encoding', 'style'],
222
+ };
223
+ ```
224
+
225
+ > `CodeContent`、`MermaidContent`、`LatexContent` 各自内部处理安全性(KaTeX `errorColor`、highlight.js 转义等),不经过 DOMPurify。
226
+
227
+ ## 关联组件
228
+
229
+ - [CodeContent](/components/rendering/code-content) — 代码 fence 高亮
230
+ - [LatexContent](/components/rendering/latex-content) — 公式渲染
231
+ - [MermaidContent](/components/rendering/mermaid-content) — Mermaid 图表
232
+ - [ContentRender](/components/rendering/content-render) — 内容类型分发入口
@@ -0,0 +1,189 @@
1
+ # MermaidContent Mermaid 图表
2
+
3
+ > 能力域:内容渲染 | 导入:`import { MermaidContent } from '@blueking/chat-x'` | since 1.0.0
4
+
5
+ 渲染 Mermaid 图表并处理渲染事件。 源码位置:src/components/markdown-token/mermaid-content/mermaid-content.vue。
6
+
7
+ **关联**:markdown-content(解析 mermaid 类型 fence 代码块后传入 token)
8
+
9
+ ---
10
+
11
+ # MermaidContent Mermaid 图表渲染
12
+ ## 源码事实
13
+
14
+ - **源码位置**:`src/components/markdown-token/mermaid-content/mermaid-content.vue`
15
+ - **能力域**:内容渲染
16
+ - **能力说明**:渲染 Mermaid 图表并处理渲染事件。
17
+
18
+ > **能力域**:内容渲染
19
+
20
+ Markdown Token 层的 Mermaid 图表渲染基础组件,被 `MarkdownContent` 在检测到 mermaid fence token 时自动调用,通常无需手动引入。
21
+
22
+ 核心能力:**按需懒加载 Mermaid**(动态 import 单例)、**三级去重跳过**(代码比对 → 语法校验 → SVG 比对)、**100ms throttle** 流式防抖、**错误静默**(parse 失败时保持上一次 SVG)。
23
+
24
+ ## 组件结构与渲染流程
25
+
26
+ ```
27
+ props.token(Token[])
28
+
29
+ ├─ extractMermaidCode(tokens)
30
+ │ → 遍历找第一个 type==='fence' && info.trim()==='mermaid' && content 非空的 token
31
+ │ → 返回 content(无匹配返回空字符串)
32
+
33
+ └─ renderMermaid(throttle 100ms,leading + trailing)
34
+
35
+ ├─ 1. newCode === lastMermaidCode → return(代码未变,跳过)
36
+ ├─ 2. lastMermaidCode = newCode
37
+ ├─ 3. getMermaidInstance() → 动态 import('mermaid') 单例,初始化一次
38
+ ├─ 4. mermaid.parse(code, { suppressErrors: true })
39
+ │ → !isValid → return(语法无效,保持上次 SVG)
40
+ ├─ 5. mermaid.render('mermaid-content-' + randomId, code) → { svg }
41
+ ├─ 6. svgDomStr.value === svg → return(SVG 无变化,跳过)
42
+ └─ 7. svgDomStr.value = svg
43
+ nextTick → emit('mounted', { get el() { return mermaidContentRef.value } })
44
+
45
+ 模板:
46
+ div.ai-mermaid-content(:key="svgDomStr",v-html="svgDomStr")
47
+ 注::key 绑定 svgDomStr,每次 SVG 变化会重建 div 而非就地 patch
48
+ ```
49
+
50
+ ## 基础用法
51
+
52
+ ```vue
53
+ <template>
54
+ <MermaidContent
55
+ :token="tokens"
56
+ @mounted="handleMounted"
57
+ />
58
+ </template>
59
+
60
+ <script setup lang="ts">
61
+ import { MermaidContent } from '@blueking/chat-x';
62
+ import type { Token } from 'markdown-it';
63
+
64
+ const tokens: Token[] = [
65
+ {
66
+ type: 'fence',
67
+ tag: 'code',
68
+ info: 'mermaid',
69
+ content: `graph TD
70
+ A[开始] --> B{判断}
71
+ B -->|是| C[执行]
72
+ B -->|否| D[结束]`,
73
+ } as Token,
74
+ ];
75
+
76
+ const handleMounted = ({ el }: { el: HTMLElement | null }) => {
77
+ // el 是 lazy getter,值为渲染后的 .ai-mermaid-content 元素
78
+ console.log('渲染完成:', el);
79
+ };
80
+ </script>
81
+ ```
82
+
83
+ ## 支持的图表类型
84
+
85
+ ### 时序图(Sequence Diagram)
86
+
87
+ ### 甘特图(Gantt)
88
+
89
+ ### 类图(Class Diagram)
90
+
91
+ ### 状态图(State Diagram)
92
+
93
+ ### 饼图(Pie Chart)
94
+
95
+ ## 流式渲染
96
+
97
+ 流式输入时 Mermaid 语法逐步完整,组件通过 throttle + `parse` 语法校验避免无效渲染:
98
+
99
+ ```vue
100
+ <template>
101
+ <MermaidContent :token="streamingTokens" />
102
+ </template>
103
+
104
+ <script setup lang="ts">
105
+ import { ref } from 'vue';
106
+ import { MermaidContent } from '@blueking/chat-x';
107
+
108
+ const streamingTokens = ref([{ type: 'fence', tag: 'code', info: 'mermaid', content: '' }]);
109
+
110
+ const simulate = async () => {
111
+ const code = `graph TD\n A[开始] --> B[处理]\n B --> C[结束]`;
112
+ let content = '';
113
+ for (const char of code) {
114
+ await new Promise(r => setTimeout(r, 50));
115
+ content += char;
116
+ streamingTokens.value = [{ type: 'fence', tag: 'code', info: 'mermaid', content }];
117
+ }
118
+ };
119
+ </script>
120
+ ```
121
+
122
+ **流式过程中的行为**:
123
+
124
+ | 阶段 | `parse` 结果 | 行为 |
125
+ | -------------------------- | ------------ | ----------------------------------------- |
126
+ | 代码未变化 | — | 三级去重第 1 关:直接跳过,不调用 Mermaid |
127
+ | 语法不完整(如 `graph T`) | `false` | 三级去重第 2 关:跳过渲染,保持上次 SVG |
128
+ | 语法完整,SVG 相同 | `true` | 三级去重第 3 关:跳过 DOM 更新 |
129
+ | 语法完整,SVG 变化 | `true` | 更新 SVG,触发 `mounted` 事件 |
130
+
131
+ ## API
132
+
133
+ ### Props
134
+
135
+ | 属性名 | 类型 | 必填 | 说明 |
136
+ | ------ | --------- | ---- | -------------------------------------------------------------------------------------------- |
137
+ | token | `Token[]` | ✓ | markdown-it Token 数组;组件自动从中提取第一个 `type==='fence' && info==='mermaid'` 的 token |
138
+
139
+ ### Events
140
+
141
+ | 事件名 | 参数 | 触发时机 |
142
+ | ------- | ----------------------------- | ---------------------------------------------------------------------------------- |
143
+ | mounted | `{ el: HTMLElement \| null }` | SVG 更新后的 `nextTick`;`el` 为 lazy getter,返回当前 `.ai-mermaid-content` 元素引用 |
144
+
145
+ ### Token 结构
146
+
147
+ ```typescript
148
+ // 组件只识别 type === 'fence' 且 info.trim() === 'mermaid' 的 token
149
+ {
150
+ type: 'fence';
151
+ tag?: 'code'; // 可选
152
+ info: 'mermaid'; // 必须严格等于 'mermaid'(trim 后)
153
+ content: string; // Mermaid 图表定义语法
154
+ }
155
+ ```
156
+
157
+ ## 性能与错误处理细节
158
+
159
+ ### 单例 Mermaid 实例
160
+
161
+ ```typescript
162
+ // 模块级变量,所有 MermaidContent 实例共享同一个 mermaid 模块
163
+ let mermaidInstance: MermaidModule | null = null;
164
+
165
+ // 初始化时调用一次(suppressErrorRendering: true 抑制 Mermaid 内部错误 UI)
166
+ mermaidInstance.default.initialize({ suppressErrorRendering: true });
167
+ ```
168
+
169
+ 首次渲染因动态 import 会有约 200~500ms 的网络加载延迟,之后复用实例无额外开销。
170
+
171
+ ### SVG ID 随机化
172
+
173
+ 每次调用 `mermaid.render` 时生成随机 ID:
174
+
175
+ ```typescript
176
+ mermaid.default.render('mermaid-content-' + Math.random().toString(36).substring(2, 15), code);
177
+ ```
178
+
179
+ 避免多个 MermaidContent 实例或同一实例多次渲染时 DOM ID 冲突。
180
+
181
+ ### 错误静默
182
+
183
+ - `mermaid.parse` 失败(语法无效)→ `return`,不修改 `svgDomStr`,保持上次成功的 SVG
184
+ - `mermaid.render` 抛出异常 → `console.warn`,不修改 `svgDomStr`,保持上次成功的 SVG
185
+ - 两种情况下组件界面均无错误提示(静默降级)
186
+
187
+ ## 关联组件
188
+
189
+ - [MarkdownContent](/components/rendering/markdown-content) — mermaid fence token 的来源与挂载