@hejiayue/x-markdown-test 0.0.1-beta.107
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/LICENSE +21 -0
- package/README.md +1090 -0
- package/dist/index-BjeepIV6.js +529 -0
- package/dist/index-BjeepIV6.js.map +1 -0
- package/dist/index-CgG50XSZ.cjs +2 -0
- package/dist/index-CgG50XSZ.cjs.map +1 -0
- package/dist/index-DtKeGkdv.cjs +2 -0
- package/dist/index-DtKeGkdv.cjs.map +1 -0
- package/dist/index-Ys7-7uFi.js +1856 -0
- package/dist/index-Ys7-7uFi.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/types/MarkdownRender/index.d.ts +441 -0
- package/dist/types/core/components.d.ts +4 -0
- package/dist/types/core/hast-to-vnode.d.ts +13 -0
- package/dist/types/core/index.d.ts +6 -0
- package/dist/types/core/useProcessor.d.ts +23 -0
- package/dist/types/hooks/index.d.ts +6 -0
- package/dist/types/hooks/useComponents.d.ts +21 -0
- package/dist/types/hooks/useHighlight.d.ts +26 -0
- package/dist/types/hooks/useMarkdown.d.ts +2 -0
- package/dist/types/hooks/useMermaid.d.ts +22 -0
- package/dist/types/hooks/usePlugins.d.ts +8 -0
- package/dist/types/hooks/useTheme.d.ts +25 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/plugins/rehypePlugin.d.ts +2 -0
- package/dist/x-markdown.cjs.js +2 -0
- package/dist/x-markdown.cjs.js.map +1 -0
- package/dist/x-markdown.es.js +20 -0
- package/dist/x-markdown.es.js.map +1 -0
- package/package.json +98 -0
package/README.md
ADDED
|
@@ -0,0 +1,1090 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# X-Markdown
|
|
4
|
+
|
|
5
|
+
一个功能强大的 Vue 3 Markdown 渲染组件库
|
|
6
|
+
|
|
7
|
+
支持流式渲染、代码高亮、LaTeX 数学公式、Mermaid 图表等特性
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/x-markdown-vue)
|
|
10
|
+
[](https://www.npmjs.com/package/x-markdown-vue)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](https://vuejs.org/)
|
|
13
|
+
|
|
14
|
+
<div align="center">
|
|
15
|
+
|
|
16
|
+
[在线演示](https://x-markdown.netlify.app/) · [报告问题](https://github.com/element-plus-x/x-markdown/issues) · [功能请求](https://github.com/element-plus-x/x-markdown/issues/new)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
## ✨ 特性
|
|
23
|
+
|
|
24
|
+
- 🚀 **Vue 3 组合式 API** - 基于 Vue 3 Composition API 构建
|
|
25
|
+
- 📝 **GitHub Flavored Markdown** - 完整支持 GFM 语法
|
|
26
|
+
- 🎨 **代码高亮** - 基于 Shiki,支持 100+ 语言和多种主题
|
|
27
|
+
- 🌊 **流式渲染** - 支持 AI 对话场景的实时输出动画
|
|
28
|
+
- 🧮 **LaTeX 数学公式** - 支持行内和块级数学公式渲染
|
|
29
|
+
- 📊 **Mermaid 图表** - 支持流程图、时序图等多种图表
|
|
30
|
+
- 🌗 **深色模式** - 内置深浅色主题切换支持
|
|
31
|
+
- 🔌 **高度可定制** - 支持自定义渲染、插槽和属性
|
|
32
|
+
- 🎭 **灵活的插件系统** - 支持 remark 和 rehype 插件扩展
|
|
33
|
+
- 🔒 **安全可靠** - 可选的 HTML 内容清理和消毒
|
|
34
|
+
- 📦 **Monorepo 架构** - 使用 pnpm workspace 和 Turbo 管理
|
|
35
|
+
|
|
36
|
+
## 📦 安装
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# pnpm (推荐)
|
|
40
|
+
pnpm add x-markdown-vue
|
|
41
|
+
|
|
42
|
+
# npm
|
|
43
|
+
npm install x-markdown-vue
|
|
44
|
+
|
|
45
|
+
# yarn
|
|
46
|
+
yarn add x-markdown-vue
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 依赖项
|
|
50
|
+
|
|
51
|
+
确保安装了对等依赖:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm add vue@^3.3.0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
如果需要 LaTeX 支持,还需要引入 KaTeX 样式:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import 'katex/dist/katex.min.css'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 🚀 快速开始
|
|
64
|
+
|
|
65
|
+
### 基础用法
|
|
66
|
+
|
|
67
|
+
```vue
|
|
68
|
+
<template>
|
|
69
|
+
<MarkdownRenderer :markdown="content" />
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<script setup lang="ts">
|
|
73
|
+
import { ref } from 'vue'
|
|
74
|
+
import { MarkdownRenderer } from 'x-markdown-vue'
|
|
75
|
+
import 'x-markdown-vue/style'
|
|
76
|
+
|
|
77
|
+
const content = ref(`
|
|
78
|
+
# Hello World
|
|
79
|
+
|
|
80
|
+
This is a **markdown** renderer.
|
|
81
|
+
`)
|
|
82
|
+
</script>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 异步渲染
|
|
86
|
+
|
|
87
|
+
对于大型文档,可以使用异步渲染模式:
|
|
88
|
+
|
|
89
|
+
```vue
|
|
90
|
+
<template>
|
|
91
|
+
<Suspense>
|
|
92
|
+
<MarkdownRendererAsync :markdown="content" />
|
|
93
|
+
<template #fallback>
|
|
94
|
+
<div>加载中...</div>
|
|
95
|
+
</template>
|
|
96
|
+
</Suspense>
|
|
97
|
+
</template>
|
|
98
|
+
|
|
99
|
+
<script setup lang="ts">
|
|
100
|
+
import { ref } from 'vue'
|
|
101
|
+
import { MarkdownRendererAsync } from 'x-markdown-vue'
|
|
102
|
+
import 'x-markdown-vue/style'
|
|
103
|
+
|
|
104
|
+
const content = ref('# Large Document\n...')
|
|
105
|
+
</script>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 📖 配置选项
|
|
109
|
+
|
|
110
|
+
### Props 属性
|
|
111
|
+
|
|
112
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
113
|
+
| --------------------- | ------------------- | ----------- | --------------------------- |
|
|
114
|
+
| `markdown` | `string` | `''` | Markdown 字符串内容 |
|
|
115
|
+
| `allowHtml` | `boolean` | `false` | 是否允许渲染 HTML |
|
|
116
|
+
| `enableLatex` | `boolean` | `true` | 是否启用 LaTeX 数学公式支持 |
|
|
117
|
+
| `enableAnimate` | `boolean` | `false` | 是否启用流式动画效果 |
|
|
118
|
+
| `enableBreaks` | `boolean` | `true` | 是否将换行符转换为 `<br>` |
|
|
119
|
+
| `isDark` | `boolean` | `false` | 是否为深色模式 |
|
|
120
|
+
| `showCodeBlockHeader` | `boolean` | `true` | 是否显示代码块头部 |
|
|
121
|
+
| `codeMaxHeight` | `string` | `undefined` | 代码块最大高度,如 '300px' |
|
|
122
|
+
| `codeBlockActions` | `CodeBlockAction[]` | `[]` | 代码块自定义操作按钮 |
|
|
123
|
+
| `mermaidActions` | `MermaidAction[]` | `[]` | Mermaid 图表自定义操作按钮 |
|
|
124
|
+
| `codeXRender` | `object` | `{}` | 自定义代码块渲染函数 |
|
|
125
|
+
| `customAttrs` | `CustomAttrs` | `{}` | 自定义属性对象 |
|
|
126
|
+
| `remarkPlugins` | `PluggableList` | `[]` | remark 插件列表 |
|
|
127
|
+
| `rehypePlugins` | `PluggableList` | `[]` | rehype 插件列表 |
|
|
128
|
+
| `sanitize` | `boolean` | `false` | 是否启用内容清洗 |
|
|
129
|
+
| `sanitizeOptions` | `SanitizeOptions` | `{}` | 清洗配置选项 |
|
|
130
|
+
|
|
131
|
+
## 🎨 主题配置
|
|
132
|
+
|
|
133
|
+
### 深色模式
|
|
134
|
+
|
|
135
|
+
通过 `isDark` 属性控制整体主题:
|
|
136
|
+
|
|
137
|
+
```vue
|
|
138
|
+
<template>
|
|
139
|
+
<MarkdownRenderer :markdown="content" :is-dark="isDark" />
|
|
140
|
+
</template>
|
|
141
|
+
|
|
142
|
+
<script setup>
|
|
143
|
+
import { ref } from 'vue'
|
|
144
|
+
|
|
145
|
+
const isDark = ref(false)
|
|
146
|
+
|
|
147
|
+
const toggleTheme = () => {
|
|
148
|
+
isDark.value = !isDark.value
|
|
149
|
+
}
|
|
150
|
+
</script>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 代码高亮主题
|
|
154
|
+
|
|
155
|
+
支持所有 [Shiki 内置主题](https://shiki.style/themes)。
|
|
156
|
+
|
|
157
|
+
## 🔧 自定义渲染
|
|
158
|
+
|
|
159
|
+
### 自定义属性
|
|
160
|
+
|
|
161
|
+
通过 `customAttrs` 为 Markdown 元素添加自定义属性:
|
|
162
|
+
|
|
163
|
+
```vue
|
|
164
|
+
<MarkdownRenderer
|
|
165
|
+
:markdown="content"
|
|
166
|
+
:custom-attrs="{
|
|
167
|
+
heading: (node, { level }) => ({
|
|
168
|
+
class: ['heading', `heading-${level}`],
|
|
169
|
+
id: `heading-${level}`,
|
|
170
|
+
}),
|
|
171
|
+
a: (node) => ({
|
|
172
|
+
target: '_blank',
|
|
173
|
+
rel: 'noopener noreferrer',
|
|
174
|
+
}),
|
|
175
|
+
}"
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 自定义插槽
|
|
180
|
+
|
|
181
|
+
组件提供了强大的插槽系统,可以自定义任何 Markdown 元素的渲染:
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<MarkdownRenderer :markdown="content">
|
|
185
|
+
<!-- 自定义标题渲染 -->
|
|
186
|
+
<template #heading="{ node, level, children }">
|
|
187
|
+
<component :is="`h${level}`" class="custom-heading">
|
|
188
|
+
<a :href="`#heading-${level}`" class="anchor">#</a>
|
|
189
|
+
<component :is="children" />
|
|
190
|
+
</component>
|
|
191
|
+
</template>
|
|
192
|
+
|
|
193
|
+
<!-- 自定义引用块渲染 -->
|
|
194
|
+
<template #blockquote="{ children }">
|
|
195
|
+
<blockquote class="custom-blockquote">
|
|
196
|
+
<div class="quote-icon">💬</div>
|
|
197
|
+
<component :is="children" />
|
|
198
|
+
</blockquote>
|
|
199
|
+
</template>
|
|
200
|
+
|
|
201
|
+
<!-- 自定义链接渲染 -->
|
|
202
|
+
<template #a="{ node, children }">
|
|
203
|
+
<a :href="node?.properties?.href" target="_blank" class="custom-link">
|
|
204
|
+
<component :is="children" />
|
|
205
|
+
<span class="external-icon">↗</span>
|
|
206
|
+
</a>
|
|
207
|
+
</template>
|
|
208
|
+
</MarkdownRenderer>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### 支持的插槽类型
|
|
212
|
+
|
|
213
|
+
- `heading` / `h1` ~ `h6` - 标题
|
|
214
|
+
- `code` / `inline-code` / `block-code` - 代码
|
|
215
|
+
- `blockquote` - 引用块
|
|
216
|
+
- `list` / `ul` / `ol` / `li` / `list-item` - 列表
|
|
217
|
+
- `table` / `thead` / `tbody` / `tr` / `td` / `th` - 表格
|
|
218
|
+
- `a` / `img` / `p` / `strong` / `em` - 行内元素
|
|
219
|
+
- 以及所有标准 HTML 标签名
|
|
220
|
+
|
|
221
|
+
### 自定义代码块渲染器
|
|
222
|
+
|
|
223
|
+
通过 `codeXRender` 自定义特定语言的代码块渲染:
|
|
224
|
+
|
|
225
|
+
```vue
|
|
226
|
+
<script setup>
|
|
227
|
+
import { h } from 'vue'
|
|
228
|
+
import EchartsRenderer from './EchartsRenderer.vue'
|
|
229
|
+
|
|
230
|
+
const codeXRender = {
|
|
231
|
+
// 自定义 echarts 代码块渲染
|
|
232
|
+
echarts: (props) => h(EchartsRenderer, { code: props.raw.content }),
|
|
233
|
+
// 自定义行内代码渲染
|
|
234
|
+
inline: (props) => h('code', { class: 'custom-inline' }, props.raw.content),
|
|
235
|
+
}
|
|
236
|
+
</script>
|
|
237
|
+
|
|
238
|
+
<template>
|
|
239
|
+
<MarkdownRenderer :markdown="content" :code-x-render="codeXRender" />
|
|
240
|
+
</template>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## 🌊 流式渲染动画
|
|
244
|
+
|
|
245
|
+
启用 `enableAnimate` 属性后,代码块中的每个 token 会添加 `x-md-animated-word` class,可配合 CSS 实现流式输出动画效果:
|
|
246
|
+
|
|
247
|
+
```vue
|
|
248
|
+
<MarkdownRenderer :markdown="content" :enable-animate="true" />
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
```css
|
|
252
|
+
/* 自定义动画样式 */
|
|
253
|
+
.x-md-animated-word {
|
|
254
|
+
animation: fadeIn 0.3s ease-in-out;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@keyframes fadeIn {
|
|
258
|
+
from {
|
|
259
|
+
opacity: 0;
|
|
260
|
+
}
|
|
261
|
+
to {
|
|
262
|
+
opacity: 1;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## 🔌 插件系统
|
|
268
|
+
|
|
269
|
+
### remark 插件
|
|
270
|
+
|
|
271
|
+
```vue
|
|
272
|
+
<script setup>
|
|
273
|
+
import remarkEmoji from 'remark-emoji'
|
|
274
|
+
|
|
275
|
+
const remarkPlugins = [remarkEmoji]
|
|
276
|
+
</script>
|
|
277
|
+
|
|
278
|
+
<template>
|
|
279
|
+
<MarkdownRenderer :markdown="content" :remark-plugins="remarkPlugins" />
|
|
280
|
+
</template>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### rehype 插件
|
|
284
|
+
|
|
285
|
+
```vue
|
|
286
|
+
<script setup>
|
|
287
|
+
import rehypeSlug from 'rehype-slug'
|
|
288
|
+
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
|
289
|
+
|
|
290
|
+
const rehypePlugins = [rehypeSlug, rehypeAutolinkHeadings]
|
|
291
|
+
</script>
|
|
292
|
+
|
|
293
|
+
<template>
|
|
294
|
+
<MarkdownRenderer :markdown="content" :rehype-plugins="rehypePlugins" />
|
|
295
|
+
</template>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## 🛡️ 安全配置
|
|
299
|
+
|
|
300
|
+
启用内容清洗以防止 XSS 攻击:
|
|
301
|
+
|
|
302
|
+
```vue
|
|
303
|
+
<MarkdownRenderer
|
|
304
|
+
:markdown="untrustedContent"
|
|
305
|
+
:sanitize="true"
|
|
306
|
+
:sanitize-options="{
|
|
307
|
+
allowedTags: ['h1', 'h2', 'p', 'a', 'code', 'pre'],
|
|
308
|
+
allowedAttributes: {
|
|
309
|
+
a: ['href', 'target'],
|
|
310
|
+
},
|
|
311
|
+
}"
|
|
312
|
+
/>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## 🎯 代码块自定义操作
|
|
316
|
+
|
|
317
|
+
通过 `codeBlockActions` 属性,可以为代码块添加自定义操作按钮,实现代码运行、复制、格式化等功能。
|
|
318
|
+
|
|
319
|
+
### CodeBlockAction 类型定义
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
interface CodeBlockAction {
|
|
323
|
+
key: string; // 操作的唯一标识
|
|
324
|
+
icon?: Component | FunctionalComponent | string | IconRenderFn; // 图标(组件、SVG字符串或渲染函数)
|
|
325
|
+
title?: string; // 悬停提示文字
|
|
326
|
+
onClick?: (props: CodeBlockSlotProps) => void; // 点击回调函数
|
|
327
|
+
disabled?: boolean; // 是否禁用
|
|
328
|
+
class?: string; // 自定义 CSS 类名
|
|
329
|
+
style?: Record<string, string>; // 自定义样式
|
|
330
|
+
show?: (props: CodeBlockSlotProps) => boolean; // 控制按钮显示逻辑
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
interface CodeBlockSlotProps {
|
|
334
|
+
language: string; // 代码块语言
|
|
335
|
+
code: string; // 代码内容
|
|
336
|
+
copy: (text: string) => void; // 复制函数
|
|
337
|
+
copied: boolean; // 是否已复制
|
|
338
|
+
collapsed: boolean; // 是否折叠
|
|
339
|
+
toggleCollapse: () => void; // 切换折叠状态
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 基础用法
|
|
344
|
+
|
|
345
|
+
```vue
|
|
346
|
+
<script setup lang="ts">
|
|
347
|
+
import { MarkdownRenderer } from 'x-markdown-vue'
|
|
348
|
+
import type { CodeBlockAction } from 'x-markdown-vue'
|
|
349
|
+
|
|
350
|
+
const codeBlockActions: CodeBlockAction[] = [
|
|
351
|
+
{
|
|
352
|
+
key: 'run',
|
|
353
|
+
title: '运行代码',
|
|
354
|
+
// 使用 SVG 字符串作为图标
|
|
355
|
+
icon: '<svg width="16" height="16" viewBox="0 0 24 24"><path d="M8 5v14l11-7L8 5z" fill="currentColor"/></svg>',
|
|
356
|
+
onClick: (props) => {
|
|
357
|
+
console.log('运行代码:', props.code)
|
|
358
|
+
alert(`运行 ${props.language} 代码`)
|
|
359
|
+
},
|
|
360
|
+
// 仅在 JavaScript/TypeScript 代码块显示
|
|
361
|
+
show: (props) => ['javascript', 'typescript', 'js', 'ts'].includes(props.language),
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
key: 'format',
|
|
365
|
+
title: '格式化代码',
|
|
366
|
+
icon: '✨',
|
|
367
|
+
onClick: (props) => {
|
|
368
|
+
// 格式化代码逻辑
|
|
369
|
+
console.log('格式化代码:', props.code)
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
]
|
|
373
|
+
</script>
|
|
374
|
+
|
|
375
|
+
<template>
|
|
376
|
+
<MarkdownRenderer :markdown="content" :code-block-actions="codeBlockActions" />
|
|
377
|
+
</template>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### 高级示例
|
|
381
|
+
|
|
382
|
+
#### 1. 使用 Vue 组件作为图标
|
|
383
|
+
|
|
384
|
+
```vue
|
|
385
|
+
<script setup lang="ts">
|
|
386
|
+
import { h } from 'vue'
|
|
387
|
+
import PlayIcon from './components/PlayIcon.vue'
|
|
388
|
+
|
|
389
|
+
const codeBlockActions = [
|
|
390
|
+
{
|
|
391
|
+
key: 'run',
|
|
392
|
+
icon: PlayIcon, // 使用 Vue 组件
|
|
393
|
+
title: '运行代码',
|
|
394
|
+
onClick: (props) => {
|
|
395
|
+
// 执行代码
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
]
|
|
399
|
+
</script>
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### 2. 使用图标渲染函数
|
|
403
|
+
|
|
404
|
+
```vue
|
|
405
|
+
<script setup lang="ts">
|
|
406
|
+
import { h } from 'vue'
|
|
407
|
+
|
|
408
|
+
const codeBlockActions = [
|
|
409
|
+
{
|
|
410
|
+
key: 'custom',
|
|
411
|
+
// 图标渲染函数,可以访问 props
|
|
412
|
+
icon: (props) => h('span', {
|
|
413
|
+
style: { color: props.copied ? 'green' : 'currentColor' }
|
|
414
|
+
}, '📋'),
|
|
415
|
+
title: '自定义操作',
|
|
416
|
+
onClick: (props) => {
|
|
417
|
+
props.copy(props.code)
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
]
|
|
421
|
+
</script>
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### 3. 条件显示和动态样式
|
|
425
|
+
|
|
426
|
+
```vue
|
|
427
|
+
<script setup lang="ts">
|
|
428
|
+
const codeBlockActions = [
|
|
429
|
+
{
|
|
430
|
+
key: 'save',
|
|
431
|
+
icon: '💾',
|
|
432
|
+
title: '保存代码',
|
|
433
|
+
// 只在代码长度超过 100 时显示
|
|
434
|
+
show: (props) => props.code.length > 100,
|
|
435
|
+
// 动态样式
|
|
436
|
+
style: {
|
|
437
|
+
color: '#42b883',
|
|
438
|
+
fontWeight: 'bold',
|
|
439
|
+
},
|
|
440
|
+
onClick: async (props) => {
|
|
441
|
+
// 保存代码到服务器
|
|
442
|
+
await saveCode(props.code, props.language)
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
key: 'expand',
|
|
447
|
+
icon: '⬇️',
|
|
448
|
+
title: '展开/折叠',
|
|
449
|
+
onClick: (props) => {
|
|
450
|
+
props.toggleCollapse()
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
]
|
|
454
|
+
</script>
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
#### 4. 集成第三方工具
|
|
458
|
+
|
|
459
|
+
```vue
|
|
460
|
+
<script setup lang="ts">
|
|
461
|
+
import { Notify } from 'quasar'
|
|
462
|
+
|
|
463
|
+
const codeBlockActions = [
|
|
464
|
+
{
|
|
465
|
+
key: 'copy-enhanced',
|
|
466
|
+
icon: '📋',
|
|
467
|
+
title: '复制代码',
|
|
468
|
+
onClick: (props) => {
|
|
469
|
+
props.copy(props.code)
|
|
470
|
+
// 显示通知
|
|
471
|
+
Notify.create({
|
|
472
|
+
message: '代码已复制到剪贴板',
|
|
473
|
+
color: 'positive',
|
|
474
|
+
icon: 'check',
|
|
475
|
+
})
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
]
|
|
479
|
+
</script>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## 📊 Mermaid 图表自定义操作
|
|
483
|
+
|
|
484
|
+
通过 `mermaidActions` 属性,可以为 Mermaid 图表添加自定义操作按钮,实现图表编辑、导出、分享等功能。
|
|
485
|
+
|
|
486
|
+
### MermaidAction 类型定义
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
interface MermaidAction {
|
|
490
|
+
key: string; // 操作的唯一标识
|
|
491
|
+
icon?: Component | FunctionalComponent | string | MermaidIconRenderFn; // 图标
|
|
492
|
+
title?: string; // 悬停提示文字
|
|
493
|
+
onClick?: (props: MermaidSlotProps) => void; // 点击回调函数
|
|
494
|
+
disabled?: boolean; // 是否禁用
|
|
495
|
+
class?: string; // 自定义 CSS 类名
|
|
496
|
+
style?: Record<string, string>; // 自定义样式
|
|
497
|
+
show?: (props: MermaidSlotProps) => boolean; // 控制按钮显示逻辑
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
interface MermaidSlotProps {
|
|
501
|
+
showSourceCode: boolean; // 是否显示源码
|
|
502
|
+
svg: string; // SVG 内容
|
|
503
|
+
rawContent: string; // 原始 Mermaid 代码
|
|
504
|
+
isLoading: boolean; // 是否加载中
|
|
505
|
+
copied: boolean; // 是否已复制
|
|
506
|
+
zoomIn: () => void; // 放大
|
|
507
|
+
zoomOut: () => void; // 缩小
|
|
508
|
+
reset: () => void; // 重置缩放
|
|
509
|
+
fullscreen: () => void; // 全屏显示
|
|
510
|
+
toggleCode: () => void; // 切换源码显示
|
|
511
|
+
copyCode: () => Promise<void>; // 复制源码
|
|
512
|
+
download: () => void; // 下载 SVG
|
|
513
|
+
raw: any; // 原始数据对象
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### 基础用法
|
|
518
|
+
|
|
519
|
+
```vue
|
|
520
|
+
<script setup lang="ts">
|
|
521
|
+
import { MarkdownRenderer } from 'x-markdown-vue'
|
|
522
|
+
import type { MermaidAction } from 'x-markdown-vue'
|
|
523
|
+
|
|
524
|
+
const mermaidActions: MermaidAction[] = [
|
|
525
|
+
{
|
|
526
|
+
key: 'edit',
|
|
527
|
+
title: '编辑图表',
|
|
528
|
+
icon: '<svg width="16" height="16" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" stroke="currentColor" stroke-width="2"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" stroke="currentColor" stroke-width="2"/></svg>',
|
|
529
|
+
onClick: (props) => {
|
|
530
|
+
// 打开编辑器,传入原始内容
|
|
531
|
+
openMermaidEditor(props.rawContent)
|
|
532
|
+
},
|
|
533
|
+
// 仅在非源码模式下显示
|
|
534
|
+
show: (props) => !props.showSourceCode,
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
key: 'share',
|
|
538
|
+
title: '分享图表',
|
|
539
|
+
icon: '🔗',
|
|
540
|
+
onClick: async (props) => {
|
|
541
|
+
// 生成分享链接
|
|
542
|
+
const shareUrl = await generateShareUrl(props.rawContent)
|
|
543
|
+
navigator.clipboard.writeText(shareUrl)
|
|
544
|
+
alert('分享链接已复制')
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
]
|
|
548
|
+
</script>
|
|
549
|
+
|
|
550
|
+
<template>
|
|
551
|
+
<MarkdownRenderer :markdown="content" :mermaid-actions="mermaidActions" />
|
|
552
|
+
</template>
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### 高级示例
|
|
556
|
+
|
|
557
|
+
#### 1. 使用内置方法
|
|
558
|
+
|
|
559
|
+
```vue
|
|
560
|
+
<script setup lang="ts">
|
|
561
|
+
const mermaidActions = [
|
|
562
|
+
{
|
|
563
|
+
key: 'zoom-in',
|
|
564
|
+
icon: '🔍+',
|
|
565
|
+
title: '放大',
|
|
566
|
+
onClick: (props) => props.zoomIn(),
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
key: 'zoom-out',
|
|
570
|
+
icon: '🔍-',
|
|
571
|
+
title: '缩小',
|
|
572
|
+
onClick: (props) => props.zoomOut(),
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
key: 'reset',
|
|
576
|
+
icon: '↺',
|
|
577
|
+
title: '重置',
|
|
578
|
+
onClick: (props) => props.reset(),
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
key: 'fullscreen',
|
|
582
|
+
icon: '⛶',
|
|
583
|
+
title: '全屏',
|
|
584
|
+
onClick: (props) => props.fullscreen(),
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
key: 'download-svg',
|
|
588
|
+
icon: '💾',
|
|
589
|
+
title: '下载 SVG',
|
|
590
|
+
onClick: (props) => props.download(),
|
|
591
|
+
},
|
|
592
|
+
]
|
|
593
|
+
</script>
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
#### 2. 导出为 PNG
|
|
597
|
+
|
|
598
|
+
```vue
|
|
599
|
+
<script setup lang="ts">
|
|
600
|
+
const mermaidActions = [
|
|
601
|
+
{
|
|
602
|
+
key: 'export-png',
|
|
603
|
+
icon: '🖼️',
|
|
604
|
+
title: '导出为 PNG',
|
|
605
|
+
onClick: async (props) => {
|
|
606
|
+
// 将 SVG 转换为 PNG
|
|
607
|
+
const canvas = document.createElement('canvas')
|
|
608
|
+
const ctx = canvas.getContext('2d')
|
|
609
|
+
const img = new Image()
|
|
610
|
+
|
|
611
|
+
img.onload = () => {
|
|
612
|
+
canvas.width = img.width
|
|
613
|
+
canvas.height = img.height
|
|
614
|
+
ctx?.drawImage(img, 0, 0)
|
|
615
|
+
|
|
616
|
+
canvas.toBlob((blob) => {
|
|
617
|
+
if (blob) {
|
|
618
|
+
const url = URL.createObjectURL(blob)
|
|
619
|
+
const a = document.createElement('a')
|
|
620
|
+
a.href = url
|
|
621
|
+
a.download = 'mermaid-chart.png'
|
|
622
|
+
a.click()
|
|
623
|
+
URL.revokeObjectURL(url)
|
|
624
|
+
}
|
|
625
|
+
})
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
img.src = 'data:image/svg+xml;base64,' + btoa(props.svg)
|
|
629
|
+
},
|
|
630
|
+
},
|
|
631
|
+
]
|
|
632
|
+
</script>
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
#### 3. 在线编辑器集成
|
|
636
|
+
|
|
637
|
+
```vue
|
|
638
|
+
<script setup lang="ts">
|
|
639
|
+
const mermaidActions = [
|
|
640
|
+
{
|
|
641
|
+
key: 'edit-online',
|
|
642
|
+
icon: '✏️',
|
|
643
|
+
title: '在 Mermaid Live Editor 中编辑',
|
|
644
|
+
onClick: (props) => {
|
|
645
|
+
// 编码 Mermaid 内容并打开在线编辑器
|
|
646
|
+
const encoded = btoa(encodeURIComponent(props.rawContent))
|
|
647
|
+
window.open(`https://mermaid.live/edit#base64:${encoded}`, '_blank')
|
|
648
|
+
},
|
|
649
|
+
},
|
|
650
|
+
]
|
|
651
|
+
</script>
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
#### 4. 条件显示和状态管理
|
|
655
|
+
|
|
656
|
+
```vue
|
|
657
|
+
<script setup lang="ts">
|
|
658
|
+
import { ref } from 'vue'
|
|
659
|
+
|
|
660
|
+
const favorites = ref<Set<string>>(new Set())
|
|
661
|
+
|
|
662
|
+
const mermaidActions = [
|
|
663
|
+
{
|
|
664
|
+
key: 'favorite',
|
|
665
|
+
icon: (props) => favorites.value.has(props.rawContent) ? '❤️' : '🤍',
|
|
666
|
+
title: '收藏',
|
|
667
|
+
onClick: (props) => {
|
|
668
|
+
if (favorites.value.has(props.rawContent)) {
|
|
669
|
+
favorites.value.delete(props.rawContent)
|
|
670
|
+
} else {
|
|
671
|
+
favorites.value.add(props.rawContent)
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
key: 'copy',
|
|
677
|
+
icon: (props) => props.copied ? '✅' : '📋',
|
|
678
|
+
title: '复制源码',
|
|
679
|
+
onClick: async (props) => {
|
|
680
|
+
await props.copyCode()
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
]
|
|
684
|
+
</script>
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
#### 5. 完整示例:图表管理工具栏
|
|
688
|
+
|
|
689
|
+
```vue
|
|
690
|
+
<script setup lang="ts">
|
|
691
|
+
import { ref } from 'vue'
|
|
692
|
+
|
|
693
|
+
const isFullscreen = ref(false)
|
|
694
|
+
|
|
695
|
+
const mermaidActions = [
|
|
696
|
+
// 视图控制组
|
|
697
|
+
{
|
|
698
|
+
key: 'toggle-code',
|
|
699
|
+
icon: (props) => props.showSourceCode ? '👁️' : '📝',
|
|
700
|
+
title: '切换源码',
|
|
701
|
+
onClick: (props) => props.toggleCode(),
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
key: 'fullscreen',
|
|
705
|
+
icon: isFullscreen.value ? '⛶' : '⛶',
|
|
706
|
+
title: '全屏',
|
|
707
|
+
onClick: (props) => {
|
|
708
|
+
props.fullscreen()
|
|
709
|
+
isFullscreen.value = !isFullscreen.value
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
|
|
713
|
+
// 缩放控制组
|
|
714
|
+
{
|
|
715
|
+
key: 'zoom-in',
|
|
716
|
+
icon: '🔍+',
|
|
717
|
+
title: '放大',
|
|
718
|
+
onClick: (props) => props.zoomIn(),
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
key: 'zoom-out',
|
|
722
|
+
icon: '🔍-',
|
|
723
|
+
title: '缩小',
|
|
724
|
+
onClick: (props) => props.zoomOut(),
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
key: 'reset-zoom',
|
|
728
|
+
icon: '↺',
|
|
729
|
+
title: '重置缩放',
|
|
730
|
+
onClick: (props) => props.reset(),
|
|
731
|
+
},
|
|
732
|
+
|
|
733
|
+
// 导出操作组
|
|
734
|
+
{
|
|
735
|
+
key: 'download',
|
|
736
|
+
icon: '💾',
|
|
737
|
+
title: '下载 SVG',
|
|
738
|
+
onClick: (props) => props.download(),
|
|
739
|
+
show: (props) => !props.isLoading,
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
key: 'copy',
|
|
743
|
+
icon: (props) => props.copied ? '✅' : '📋',
|
|
744
|
+
title: '复制源码',
|
|
745
|
+
onClick: async (props) => await props.copyCode(),
|
|
746
|
+
},
|
|
747
|
+
|
|
748
|
+
// 编辑操作
|
|
749
|
+
{
|
|
750
|
+
key: 'edit',
|
|
751
|
+
icon: '✏️',
|
|
752
|
+
title: '编辑',
|
|
753
|
+
onClick: (props) => {
|
|
754
|
+
console.log('编辑 Mermaid 图表:', props.rawContent)
|
|
755
|
+
},
|
|
756
|
+
show: (props) => !props.showSourceCode && !props.isLoading,
|
|
757
|
+
},
|
|
758
|
+
]
|
|
759
|
+
</script>
|
|
760
|
+
|
|
761
|
+
<template>
|
|
762
|
+
<MarkdownRenderer
|
|
763
|
+
:markdown="content"
|
|
764
|
+
:mermaid-actions="mermaidActions"
|
|
765
|
+
/>
|
|
766
|
+
</template>
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### 样式自定义
|
|
770
|
+
|
|
771
|
+
可以通过 `class` 和 `style` 属性自定义按钮样式:
|
|
772
|
+
|
|
773
|
+
```vue
|
|
774
|
+
<script setup lang="ts">
|
|
775
|
+
const mermaidActions = [
|
|
776
|
+
{
|
|
777
|
+
key: 'custom-style',
|
|
778
|
+
icon: '⭐',
|
|
779
|
+
title: '自定义样式按钮',
|
|
780
|
+
class: 'my-custom-btn',
|
|
781
|
+
style: {
|
|
782
|
+
color: '#42b883',
|
|
783
|
+
backgroundColor: '#e8f5f0',
|
|
784
|
+
padding: '8px 12px',
|
|
785
|
+
borderRadius: '6px',
|
|
786
|
+
fontWeight: 'bold',
|
|
787
|
+
},
|
|
788
|
+
onClick: () => {
|
|
789
|
+
console.log('点击了自定义样式按钮')
|
|
790
|
+
},
|
|
791
|
+
},
|
|
792
|
+
]
|
|
793
|
+
</script>
|
|
794
|
+
|
|
795
|
+
<style>
|
|
796
|
+
.my-custom-btn:hover {
|
|
797
|
+
background-color: #d1ede3 !important;
|
|
798
|
+
transform: scale(1.05);
|
|
799
|
+
transition: all 0.2s;
|
|
800
|
+
}
|
|
801
|
+
</style>
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
## 🌟 功能演示
|
|
805
|
+
|
|
806
|
+
### 代码高亮
|
|
807
|
+
|
|
808
|
+
支持 100+ 编程语言的语法高亮,基于 Shiki 引擎:
|
|
809
|
+
|
|
810
|
+
````markdown
|
|
811
|
+
```javascript
|
|
812
|
+
function greet(name) {
|
|
813
|
+
console.log(`Hello, ${name}!`)
|
|
814
|
+
}
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
```python
|
|
818
|
+
def fibonacci(n):
|
|
819
|
+
if n <= 1:
|
|
820
|
+
return n
|
|
821
|
+
return fibonacci(n-1) + fibonacci(n-2)
|
|
822
|
+
```
|
|
823
|
+
````
|
|
824
|
+
|
|
825
|
+
### LaTeX 数学公式
|
|
826
|
+
|
|
827
|
+
支持行内和块级数学公式:
|
|
828
|
+
|
|
829
|
+
```markdown
|
|
830
|
+
行内公式: $E = mc^2$
|
|
831
|
+
|
|
832
|
+
块级公式:
|
|
833
|
+
|
|
834
|
+
$$
|
|
835
|
+
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
|
|
836
|
+
$$
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Mermaid 图表
|
|
840
|
+
|
|
841
|
+
X-Markdown 支持完整的 Mermaid 图表渲染,包括流程图、时序图、甘特图、类图、状态图、饼图、ER 图等多种图表类型,并提供丰富的交互功能。
|
|
842
|
+
|
|
843
|
+
## 流程图 (Flowchart)
|
|
844
|
+
|
|
845
|
+
```mermaid
|
|
846
|
+
graph TB
|
|
847
|
+
A[开始] --> B{是否登录?}
|
|
848
|
+
B -->|是| C[进入首页]
|
|
849
|
+
B -->|否| D[跳转登录页]
|
|
850
|
+
D --> E[输入账号密码]
|
|
851
|
+
E --> F{验证通过?}
|
|
852
|
+
F -->|是| C
|
|
853
|
+
F -->|否| G[显示错误]
|
|
854
|
+
G --> E
|
|
855
|
+
C --> H[结束]
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
## 时序图 (Sequence Diagram)
|
|
859
|
+
|
|
860
|
+
```mermaid
|
|
861
|
+
sequenceDiagram
|
|
862
|
+
participant U as 用户
|
|
863
|
+
participant C as 客户端
|
|
864
|
+
participant S as 服务器
|
|
865
|
+
participant D as 数据库
|
|
866
|
+
|
|
867
|
+
U->>C: 点击登录
|
|
868
|
+
C->>S: POST /api/login
|
|
869
|
+
S->>D: 查询用户信息
|
|
870
|
+
D-->>S: 返回用户数据
|
|
871
|
+
S-->>C: 返回 JWT Token
|
|
872
|
+
C-->>U: 登录成功,跳转首页
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
## 甘特图 (Gantt Chart)
|
|
876
|
+
|
|
877
|
+
```mermaid
|
|
878
|
+
gantt
|
|
879
|
+
title 项目开发计划
|
|
880
|
+
dateFormat YYYY-MM-DD
|
|
881
|
+
section 需求分析
|
|
882
|
+
需求调研 :a1, 2024-01-01, 7d
|
|
883
|
+
需求文档 :after a1, 5d
|
|
884
|
+
section 设计阶段
|
|
885
|
+
UI 设计 :2024-01-10, 10d
|
|
886
|
+
架构设计 :2024-01-12, 8d
|
|
887
|
+
section 开发阶段
|
|
888
|
+
前端开发 :2024-01-20, 20d
|
|
889
|
+
后端开发 :2024-01-20, 25d
|
|
890
|
+
section 测试上线
|
|
891
|
+
集成测试 :2024-02-15, 10d
|
|
892
|
+
上线部署 :2024-02-25, 3d
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
## 类图 (Class Diagram)
|
|
896
|
+
|
|
897
|
+
```mermaid
|
|
898
|
+
classDiagram
|
|
899
|
+
class Animal {
|
|
900
|
+
+String name
|
|
901
|
+
+int age
|
|
902
|
+
+makeSound()
|
|
903
|
+
}
|
|
904
|
+
class Dog {
|
|
905
|
+
+String breed
|
|
906
|
+
+bark()
|
|
907
|
+
+fetch()
|
|
908
|
+
}
|
|
909
|
+
class Cat {
|
|
910
|
+
+String color
|
|
911
|
+
+meow()
|
|
912
|
+
+scratch()
|
|
913
|
+
}
|
|
914
|
+
class Bird {
|
|
915
|
+
+float wingspan
|
|
916
|
+
+fly()
|
|
917
|
+
+sing()
|
|
918
|
+
}
|
|
919
|
+
Animal <|-- Dog
|
|
920
|
+
Animal <|-- Cat
|
|
921
|
+
Animal <|-- Bird
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
## 状态图 (State Diagram)
|
|
925
|
+
|
|
926
|
+
```mermaid
|
|
927
|
+
stateDiagram-v2
|
|
928
|
+
[*] --> 待处理
|
|
929
|
+
待处理 --> 处理中 : 开始处理
|
|
930
|
+
处理中 --> 已完成 : 处理成功
|
|
931
|
+
处理中 --> 失败 : 处理失败
|
|
932
|
+
失败 --> 处理中 : 重试
|
|
933
|
+
失败 --> 已取消 : 取消
|
|
934
|
+
已完成 --> [*]
|
|
935
|
+
已取消 --> [*]
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
## 饼图 (Pie Chart)
|
|
939
|
+
|
|
940
|
+
```mermaid
|
|
941
|
+
pie showData
|
|
942
|
+
title 技术栈使用占比
|
|
943
|
+
"Vue.js" : 35
|
|
944
|
+
"React" : 30
|
|
945
|
+
"Angular" : 15
|
|
946
|
+
"Svelte" : 10
|
|
947
|
+
"其他" : 10
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
## ER 图 (Entity Relationship)
|
|
951
|
+
|
|
952
|
+
```mermaid
|
|
953
|
+
erDiagram
|
|
954
|
+
USER ||--o{ ORDER : places
|
|
955
|
+
USER {
|
|
956
|
+
int id PK
|
|
957
|
+
string name
|
|
958
|
+
string email
|
|
959
|
+
}
|
|
960
|
+
ORDER ||--|{ ORDER_ITEM : contains
|
|
961
|
+
ORDER {
|
|
962
|
+
int id PK
|
|
963
|
+
date created_at
|
|
964
|
+
int user_id FK
|
|
965
|
+
}
|
|
966
|
+
ORDER_ITEM }|--|| PRODUCT : references
|
|
967
|
+
ORDER_ITEM {
|
|
968
|
+
int id PK
|
|
969
|
+
int quantity
|
|
970
|
+
int order_id FK
|
|
971
|
+
int product_id FK
|
|
972
|
+
}
|
|
973
|
+
PRODUCT {
|
|
974
|
+
int id PK
|
|
975
|
+
string name
|
|
976
|
+
float price
|
|
977
|
+
}
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
### 表格
|
|
981
|
+
|
|
982
|
+
支持 GFM 表格语法:
|
|
983
|
+
|
|
984
|
+
```markdown
|
|
985
|
+
| 特性 | 状态 |
|
|
986
|
+
| -------- | ---- |
|
|
987
|
+
| Markdown | ✅ |
|
|
988
|
+
| 代码高亮 | ✅ |
|
|
989
|
+
| LaTeX | ✅ |
|
|
990
|
+
| Mermaid | ✅ |
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
### 任务列表
|
|
994
|
+
|
|
995
|
+
```markdown
|
|
996
|
+
- [x] 支持基础 Markdown
|
|
997
|
+
- [x] 添加语法高亮
|
|
998
|
+
- [x] 实现 LaTeX 支持
|
|
999
|
+
- [x] 添加 Mermaid 图表
|
|
1000
|
+
- [ ] 更多功能开发中...
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
## 💡 使用场景
|
|
1004
|
+
|
|
1005
|
+
- **AI 对话应用** - 支持流式渲染,适合 ChatGPT 类应用
|
|
1006
|
+
- **技术文档站点** - 完整的 Markdown 支持,代码高亮
|
|
1007
|
+
- **博客系统** - 丰富的格式支持和自定义能力
|
|
1008
|
+
- **在线编辑器** - 实时预览 Markdown 内容
|
|
1009
|
+
- **知识库系统** - 支持数学公式和图表
|
|
1010
|
+
|
|
1011
|
+
## 🔧 技术栈
|
|
1012
|
+
|
|
1013
|
+
- **[Vue 3](https://vuejs.org/)** - 渐进式 JavaScript 框架
|
|
1014
|
+
- **[TypeScript](https://www.typescriptlang.org/)** - 类型安全的 JavaScript 超集
|
|
1015
|
+
- **[Unified](https://unifiedjs.com/)** - Markdown/HTML 处理生态系统
|
|
1016
|
+
- **[remark](https://remark.js.org/)** - Markdown 解析器
|
|
1017
|
+
- **[rehype](https://github.com/rehypejs/rehype)** - HTML 处理器
|
|
1018
|
+
- **[Shiki](https://shiki.style/)** - 语法高亮引擎
|
|
1019
|
+
- **[KaTeX](https://katex.org/)** - 数学公式渲染
|
|
1020
|
+
- **[Mermaid](https://mermaid.js.org/)** - 图表生成
|
|
1021
|
+
- **[DOMPurify](https://github.com/cure53/DOMPurify)** - HTML 清理工具
|
|
1022
|
+
- **[Vite](https://vitejs.dev/)** - 下一代前端构建工具
|
|
1023
|
+
- **[Turbo](https://turbo.build/)** - 高性能构建系统
|
|
1024
|
+
|
|
1025
|
+
## 📁 项目结构
|
|
1026
|
+
|
|
1027
|
+
```
|
|
1028
|
+
x-markdown/
|
|
1029
|
+
├── packages/
|
|
1030
|
+
│ ├── x-markdown/ # 核心组件库
|
|
1031
|
+
│ │ ├── src/
|
|
1032
|
+
│ │ │ ├── components/ # Vue 组件
|
|
1033
|
+
│ │ │ │ ├── CodeBlock/ # 代码块组件
|
|
1034
|
+
│ │ │ │ ├── CodeLine/ # 行内代码组件
|
|
1035
|
+
│ │ │ │ ├── CodeX/ # 代码渲染调度器
|
|
1036
|
+
│ │ │ │ └── Mermaid/ # Mermaid 图表组件
|
|
1037
|
+
│ │ │ ├── core/ # 核心渲染逻辑
|
|
1038
|
+
│ │ │ ├── hooks/ # 组合式函数
|
|
1039
|
+
│ │ │ ├── plugins/ # 内置插件
|
|
1040
|
+
│ │ │ └── MarkdownRender/ # 主渲染组件
|
|
1041
|
+
│ │ └── package.json
|
|
1042
|
+
│ └── playground/ # 演示应用
|
|
1043
|
+
├── pnpm-workspace.yaml
|
|
1044
|
+
├── turbo.json
|
|
1045
|
+
└── package.json
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
## 🤝 贡献
|
|
1049
|
+
|
|
1050
|
+
欢迎提交 Issue 和 Pull Request!
|
|
1051
|
+
|
|
1052
|
+
### 开发流程
|
|
1053
|
+
|
|
1054
|
+
1. Fork 本仓库
|
|
1055
|
+
2. 创建你的特性分支 (`git checkout -b feature/AmazingFeature`)
|
|
1056
|
+
3. 提交你的改动 (`git commit -m 'Add some AmazingFeature'`)
|
|
1057
|
+
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
|
1058
|
+
5. 提交 Pull Request
|
|
1059
|
+
|
|
1060
|
+
### 开发指南
|
|
1061
|
+
|
|
1062
|
+
```bash
|
|
1063
|
+
# 克隆仓库
|
|
1064
|
+
git clone https://github.com/element-plus-x/x-markdown.git
|
|
1065
|
+
cd x-markdown
|
|
1066
|
+
|
|
1067
|
+
# 安装依赖
|
|
1068
|
+
pnpm install
|
|
1069
|
+
|
|
1070
|
+
# 启动开发服务器
|
|
1071
|
+
pnpm dev
|
|
1072
|
+
|
|
1073
|
+
# 构建项目
|
|
1074
|
+
pnpm build
|
|
1075
|
+
|
|
1076
|
+
# 格式化代码
|
|
1077
|
+
pnpm format
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
## 📄 License
|
|
1081
|
+
|
|
1082
|
+
[MIT](./LICENSE) License © 2025 [element-plus-x](https://github.com/element-plus-x)
|
|
1083
|
+
|
|
1084
|
+
---
|
|
1085
|
+
|
|
1086
|
+
<div align="center">
|
|
1087
|
+
|
|
1088
|
+
如果这个项目对你有帮助,请给它一个 ⭐️
|
|
1089
|
+
|
|
1090
|
+
</div>
|