@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/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
+ [![NPM version](https://img.shields.io/npm/v/x-markdown-vue.svg)](https://www.npmjs.com/package/x-markdown-vue)
10
+ [![NPM downloads](https://img.shields.io/npm/dm/x-markdown-vue.svg)](https://www.npmjs.com/package/x-markdown-vue)
11
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
12
+ [![Vue](https://img.shields.io/badge/vue-3.x-brightgreen.svg)](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>