mio-previewer 0.1.3 → 0.1.5

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 (124) hide show
  1. package/README.md +408 -141
  2. package/README.zh-CN.md +404 -125
  3. package/dist/AlertPlugin-B74_-nlo.cjs +3 -0
  4. package/dist/AlertPlugin-DUG0ldg_.js +66 -0
  5. package/dist/{_basePickBy-xJ9BT3zN.cjs → _basePickBy-DVE1TNXC.cjs} +1 -1
  6. package/dist/{_basePickBy-BPvpJ2um.js → _basePickBy-eLNY48BA.js} +2 -2
  7. package/dist/{_baseUniq-BZgquYGf.cjs → _baseUniq-CsrG_oBm.cjs} +1 -1
  8. package/dist/{_baseUniq-Tf9Kt8z-.js → _baseUniq-Db85A0t5.js} +1 -1
  9. package/dist/{arc-C73RRLiG.cjs → arc-omcJcwL3.cjs} +1 -1
  10. package/dist/{arc-Dr6aCVTp.js → arc-xWD0pw5h.js} +1 -1
  11. package/dist/{architecture-O4VJ6CD3-DksHFJ_w.cjs → architecture-O4VJ6CD3-DS0gsucM.cjs} +1 -1
  12. package/dist/{architecture-O4VJ6CD3-CeeoNnpL.js → architecture-O4VJ6CD3-OmCnGY-G.js} +1 -1
  13. package/dist/{architectureDiagram-VXUJARFQ-CoK0Gwu-.js → architectureDiagram-VXUJARFQ-CkVk2S0A.js} +3 -3
  14. package/dist/{architectureDiagram-VXUJARFQ-3NLUlleK.cjs → architectureDiagram-VXUJARFQ-mdyHLeOz.cjs} +1 -1
  15. package/dist/{blockDiagram-VD42YOAC-BK-0UQu9.cjs → blockDiagram-VD42YOAC-CYpjD9I4.cjs} +1 -1
  16. package/dist/{blockDiagram-VD42YOAC-B7F_8nB6.js → blockDiagram-VD42YOAC-DaMjTa0C.js} +5 -5
  17. package/dist/{c4Diagram-YG6GDRKO-SAX7mzVM.cjs → c4Diagram-YG6GDRKO-DVNaP7kB.cjs} +1 -1
  18. package/dist/{c4Diagram-YG6GDRKO-DzMoPOvT.js → c4Diagram-YG6GDRKO-DonOCmA8.js} +2 -2
  19. package/dist/{channel-DZNU43d3.js → channel-B486ftOX.js} +1 -1
  20. package/dist/channel-wbveyzLS.cjs +1 -0
  21. package/dist/{chunk-4BX2VUAB-BM6KMQlI.js → chunk-4BX2VUAB-C6w9Js6N.js} +1 -1
  22. package/dist/{chunk-4BX2VUAB-BNg9BEzs.cjs → chunk-4BX2VUAB-ChbzOXZw.cjs} +1 -1
  23. package/dist/{chunk-55IACEB6-CDfNhGdc.js → chunk-55IACEB6-CwVAbm6z.js} +1 -1
  24. package/dist/{chunk-55IACEB6-CIkpKv5G.cjs → chunk-55IACEB6-D-33yVA5.cjs} +1 -1
  25. package/dist/{chunk-B4BG7PRW-DBjDqSED.js → chunk-B4BG7PRW-DrzZmWQJ.js} +4 -4
  26. package/dist/{chunk-B4BG7PRW-DXRjU9TI.cjs → chunk-B4BG7PRW-DuZZcGQH.cjs} +1 -1
  27. package/dist/{chunk-DI55MBZ5-D6sD1SDV.cjs → chunk-DI55MBZ5-CHDlmh3z.cjs} +1 -1
  28. package/dist/{chunk-DI55MBZ5-BCMfI46s.js → chunk-DI55MBZ5-CNPyCRNf.js} +3 -3
  29. package/dist/{chunk-FMBD7UC4-hNxmxOeA.cjs → chunk-FMBD7UC4-CnXch5Qs.cjs} +1 -1
  30. package/dist/{chunk-FMBD7UC4-C-N17wry.js → chunk-FMBD7UC4-DnkBtCqY.js} +1 -1
  31. package/dist/{chunk-QN33PNHL-E13ckPQD.js → chunk-QN33PNHL-BbAoMVzz.js} +1 -1
  32. package/dist/{chunk-QN33PNHL-DD0xRcz_.cjs → chunk-QN33PNHL-BlRWoDnV.cjs} +1 -1
  33. package/dist/{chunk-QZHKN3VN-Kkn2ItIi.cjs → chunk-QZHKN3VN-5fxikjdo.cjs} +1 -1
  34. package/dist/{chunk-QZHKN3VN-CJGCT_qs.js → chunk-QZHKN3VN-BJYsUa-h.js} +1 -1
  35. package/dist/{chunk-TZMSLE5B-B32hxMvx.cjs → chunk-TZMSLE5B-6qnVCnWY.cjs} +1 -1
  36. package/dist/{chunk-TZMSLE5B-DvKudy0L.js → chunk-TZMSLE5B-hAlPmzmK.js} +1 -1
  37. package/dist/{classDiagram-v2-WZHVMYZB-BmtUBt0j.js → classDiagram-2ON5EDUG-CGcrYift.js} +2 -2
  38. package/dist/{classDiagram-2ON5EDUG-x5SSUt5v.cjs → classDiagram-2ON5EDUG-CLGdd0_Z.cjs} +1 -1
  39. package/dist/{classDiagram-2ON5EDUG-BmtUBt0j.js → classDiagram-v2-WZHVMYZB-CGcrYift.js} +2 -2
  40. package/dist/{classDiagram-v2-WZHVMYZB-x5SSUt5v.cjs → classDiagram-v2-WZHVMYZB-CLGdd0_Z.cjs} +1 -1
  41. package/dist/clone-Bans8tLG.cjs +1 -0
  42. package/dist/{clone-AbZIjD3b.js → clone-DNjp7kbc.js} +1 -1
  43. package/dist/{cose-bilkent-S5V4N54A-Bdj7Vz_1.js → cose-bilkent-S5V4N54A-BzRqHvjq.js} +1 -1
  44. package/dist/{cose-bilkent-S5V4N54A-DJ49z974.cjs → cose-bilkent-S5V4N54A-CE_6-gPk.cjs} +1 -1
  45. package/dist/{custom-Bj6wd8Zo.cjs → custom-CCK8DUtS.cjs} +90 -48
  46. package/dist/{custom-DpenvaVL.js → custom-IdAwxsT0.js} +3153 -3094
  47. package/dist/{dagre-6UL2VRFP-wwVKK1c4.js → dagre-6UL2VRFP-B3ff7Qa0.js} +6 -6
  48. package/dist/{dagre-6UL2VRFP-e70bbbAo.cjs → dagre-6UL2VRFP-C8h2QmYJ.cjs} +1 -1
  49. package/dist/{diagram-PSM6KHXK-BvHkTFl-.js → diagram-PSM6KHXK-CwDc0n1y.js} +4 -4
  50. package/dist/{diagram-PSM6KHXK-ByERYM-3.cjs → diagram-PSM6KHXK-DY7M1J0U.cjs} +1 -1
  51. package/dist/{diagram-QEK2KX5R-piVunPtl.cjs → diagram-QEK2KX5R-7LB8awLg.cjs} +1 -1
  52. package/dist/{diagram-QEK2KX5R-DDeHGuBu.js → diagram-QEK2KX5R-B5zlx6uC.js} +3 -3
  53. package/dist/{diagram-S2PKOQOG-Cr055G-z.cjs → diagram-S2PKOQOG-DdadVvM8.cjs} +1 -1
  54. package/dist/{diagram-S2PKOQOG-BKInMDUf.js → diagram-S2PKOQOG-OtcMeBMe.js} +3 -3
  55. package/dist/{erDiagram-Q2GNP2WA-B4-4JFTr.js → erDiagram-Q2GNP2WA-C2LSeZL7.js} +4 -4
  56. package/dist/{erDiagram-Q2GNP2WA-B8J7KiVg.cjs → erDiagram-Q2GNP2WA-Dl2XuLmP.cjs} +1 -1
  57. package/dist/{flowDiagram-NV44I4VS-QOrkavK7.cjs → flowDiagram-NV44I4VS-97EAn9XA.cjs} +1 -1
  58. package/dist/{flowDiagram-NV44I4VS-5cNi0vQA.js → flowDiagram-NV44I4VS-CKDrEgDC.js} +5 -5
  59. package/dist/{ganttDiagram-LVOFAZNH-CigIkVoy.cjs → ganttDiagram-LVOFAZNH-BbIlc35J.cjs} +1 -1
  60. package/dist/{ganttDiagram-LVOFAZNH-DymzdMvs.js → ganttDiagram-LVOFAZNH-DfkshJiH.js} +2 -2
  61. package/dist/{gitGraph-ZV4HHKMB-CWbWsOyk.cjs → gitGraph-ZV4HHKMB-C6zvlbKy.cjs} +1 -1
  62. package/dist/{gitGraph-ZV4HHKMB-B-D8cNhE.js → gitGraph-ZV4HHKMB-ybVsjPzA.js} +1 -1
  63. package/dist/{gitGraphDiagram-NY62KEGX-CaafXshn.cjs → gitGraphDiagram-NY62KEGX-BaI23Cyn.cjs} +1 -1
  64. package/dist/{gitGraphDiagram-NY62KEGX-TPmwKAE3.js → gitGraphDiagram-NY62KEGX-BkSiHbh-.js} +4 -4
  65. package/dist/{graph-DxA9vrvy.cjs → graph-B5ZoHckb.cjs} +1 -1
  66. package/dist/{graph-DuYupv9-.js → graph-D8I9GkNk.js} +2 -2
  67. package/dist/{info-63CPKGFF-B0dB6Gmo.cjs → info-63CPKGFF-6eKHmqS-.cjs} +1 -1
  68. package/dist/info-63CPKGFF-BUd_m-Si.js +5 -0
  69. package/dist/{infoDiagram-F6ZHWCRC-BRxO2gbr.js → infoDiagram-F6ZHWCRC-BMMAyAdj.js} +2 -2
  70. package/dist/{infoDiagram-F6ZHWCRC-BmeO40po.cjs → infoDiagram-F6ZHWCRC-DIRSzuRh.cjs} +1 -1
  71. package/dist/{journeyDiagram-XKPGCS4Q-DC3T_hOS.cjs → journeyDiagram-XKPGCS4Q-C8IeHV-s.cjs} +1 -1
  72. package/dist/{journeyDiagram-XKPGCS4Q-B5MOGiml.js → journeyDiagram-XKPGCS4Q-DO73Fqz4.js} +4 -4
  73. package/dist/{kanban-definition-3W4ZIXB7-C0DqXzkl.cjs → kanban-definition-3W4ZIXB7-BAJ5FzmH.cjs} +1 -1
  74. package/dist/{kanban-definition-3W4ZIXB7-DgJ6Uj7K.js → kanban-definition-3W4ZIXB7-Dh8GKJ2U.js} +2 -2
  75. package/dist/{layout-C2ZYHFpX.js → layout-C9FQT4er.js} +4 -4
  76. package/dist/{layout-DWd-riGk.cjs → layout-EG3PPlQF.cjs} +1 -1
  77. package/dist/{linear-CHYqhRsW.cjs → linear-P18TKbMd.cjs} +1 -1
  78. package/dist/{linear-BOcw0RYN.js → linear-WyvCjWfX.js} +1 -1
  79. package/dist/{mermaid-parser.core-2hw0AO3p.cjs → mermaid-parser.core-D6oiFfri.cjs} +2 -2
  80. package/dist/{mermaid-parser.core-9Cm7d5-2.js → mermaid-parser.core-DZzEoXek.js} +11 -11
  81. package/dist/{mindmap-definition-VGOIOE7T-z7ScFjvc.cjs → mindmap-definition-VGOIOE7T-C_quwk04.cjs} +1 -1
  82. package/dist/{mindmap-definition-VGOIOE7T-DqOPFPo-.js → mindmap-definition-VGOIOE7T-DJv6Etzn.js} +3 -3
  83. package/dist/mio-previewer.cjs.js +2 -2
  84. package/dist/mio-previewer.css +1 -1
  85. package/dist/mio-previewer.es.js +12 -4
  86. package/dist/{packet-HUATNLJX-CZHu-nbR.cjs → packet-HUATNLJX-BP2PL506.cjs} +1 -1
  87. package/dist/{packet-HUATNLJX-1wKSvaMq.js → packet-HUATNLJX-CBmfZU1b.js} +1 -1
  88. package/dist/pie-WTHONI2E-CTg9RtIm.js +5 -0
  89. package/dist/{pie-WTHONI2E-DXv4_T2x.cjs → pie-WTHONI2E-D9uuNfvy.cjs} +1 -1
  90. package/dist/{pieDiagram-ADFJNKIX-D2Z---Zh.cjs → pieDiagram-ADFJNKIX-Cli4W-Cd.cjs} +1 -1
  91. package/dist/{pieDiagram-ADFJNKIX-D6VHJbDG.js → pieDiagram-ADFJNKIX-kTbzcM2c.js} +4 -4
  92. package/dist/plugins/custom.cjs.js +1 -1
  93. package/dist/plugins/custom.es.js +1 -1
  94. package/dist/plugins/markdown-it.cjs.js +1 -1
  95. package/dist/plugins/markdown-it.es.js +66 -78
  96. package/dist/{quadrantDiagram-AYHSOK5B-DkReeODO.cjs → quadrantDiagram-AYHSOK5B-BN3oiHK0.cjs} +1 -1
  97. package/dist/{quadrantDiagram-AYHSOK5B-D5OPLeMW.js → quadrantDiagram-AYHSOK5B-BoWJsSRs.js} +2 -2
  98. package/dist/{radar-NJJJXTRR-CsSvUZzP.cjs → radar-NJJJXTRR-6s1MXgpO.cjs} +1 -1
  99. package/dist/radar-NJJJXTRR-EHgY_Bp9.js +5 -0
  100. package/dist/{requirementDiagram-UZGBJVZJ-C5hVzY2x.cjs → requirementDiagram-UZGBJVZJ-Cv4g11kh.cjs} +1 -1
  101. package/dist/{requirementDiagram-UZGBJVZJ-BtuFN9mE.js → requirementDiagram-UZGBJVZJ-DfeezqhH.js} +3 -3
  102. package/dist/{sankeyDiagram-TZEHDZUN-DpRrZxqg.cjs → sankeyDiagram-TZEHDZUN-Ci99ek50.cjs} +1 -1
  103. package/dist/{sankeyDiagram-TZEHDZUN-Cg-JIJqC.js → sankeyDiagram-TZEHDZUN-DnJ5Q_82.js} +1 -1
  104. package/dist/{sequenceDiagram-WL72ISMW-KoQgtSet.cjs → sequenceDiagram-WL72ISMW-B-x48OW0.cjs} +1 -1
  105. package/dist/{sequenceDiagram-WL72ISMW-nEmJoaMy.js → sequenceDiagram-WL72ISMW-CGSwMa_I.js} +3 -3
  106. package/dist/{stateDiagram-FKZM4ZOC-DT6rGE9e.cjs → stateDiagram-FKZM4ZOC-CDTWIBaR.cjs} +1 -1
  107. package/dist/{stateDiagram-FKZM4ZOC-DBDLAMfm.js → stateDiagram-FKZM4ZOC-DnxlIDvy.js} +4 -4
  108. package/dist/{stateDiagram-v2-4FDKWEC3-uHZFzERJ.cjs → stateDiagram-v2-4FDKWEC3-BX076pCs.cjs} +1 -1
  109. package/dist/{stateDiagram-v2-4FDKWEC3-BlnZMiIk.js → stateDiagram-v2-4FDKWEC3-DsI4gK5l.js} +2 -2
  110. package/dist/{timeline-definition-IT6M3QCI-nu6lhLaG.js → timeline-definition-IT6M3QCI-BZ1Bt6EI.js} +2 -2
  111. package/dist/{timeline-definition-IT6M3QCI-5sT2JElf.cjs → timeline-definition-IT6M3QCI-doRyfVBa.cjs} +1 -1
  112. package/dist/{treemap-75Q7IDZK-0YVmrH6l.cjs → treemap-75Q7IDZK-CJKHGaSh.cjs} +1 -1
  113. package/dist/{treemap-75Q7IDZK-CjQGnPQL.js → treemap-75Q7IDZK-CmDuYBJ9.js} +1 -1
  114. package/dist/types/helpers/containerHelpers.d.ts +11 -0
  115. package/dist/types/index.d.ts +1 -1
  116. package/dist/types/plugins/AlertPlugin.d.ts +10 -8
  117. package/dist/{xychartDiagram-PRI3JC2R-Df-nQpxQ.cjs → xychartDiagram-PRI3JC2R-B88yMO5N.cjs} +1 -1
  118. package/dist/{xychartDiagram-PRI3JC2R-COTy5kPs.js → xychartDiagram-PRI3JC2R-BL9ENoB-.js} +2 -2
  119. package/package.json +1 -1
  120. package/dist/channel-K9KCfQVN.cjs +0 -1
  121. package/dist/clone-BIUMbfGI.cjs +0 -1
  122. package/dist/info-63CPKGFF-C4jcTOlN.js +0 -5
  123. package/dist/pie-WTHONI2E-Tnd3n2cn.js +0 -5
  124. package/dist/radar-NJJJXTRR-B7MWPc1b.js +0 -5
package/README.zh-CN.md CHANGED
@@ -2,205 +2,484 @@
2
2
 
3
3
  [English](./README.md) | 中文文档
4
4
 
5
- 一个针对流式更新优化的小型 Vue 3 Markd## 流式行为与光标管理
5
+ 一个针对流式更新优化的 Vue 3 Markdown 渲染器,具有强大的插件系统。支持实时渲染、语法高亮、数学公式、图表等功能。
6
6
 
7
- `isStreaming` prop 控制是否在渲染内容末尾显示闪烁的光标:
7
+ **核心特性:**
8
+ - 🚀 支持流式实时渲染
9
+ - 🎨 内置语法高亮(Prism.js,20+ 种语言)
10
+ - 📐 数学公式支持(KaTeX)
11
+ - 📊 图表渲染(Mermaid)
12
+ - 🔌 可扩展的插件系统
13
+ - 📦 支持 Tree-shaking,轻量级
14
+ - 🎯 TypeScript 支持
8
15
 
9
- - `isStreaming=false` — 不显示光标。用于静态内容或流式更新已结束的情况。
10
- - `isStreaming=true` — 在末尾显示闪烁光标,表示内容正在流式更新中。
16
+ ## 安装
11
17
 
12
- 当 `isStreaming` 为 `true` 时,会在 AST 末尾插入一个特殊节点 `{ type: 'component', name: 'cursor' }` 来渲染 `BlinkingCursor` 组件。辅助函数 `manageCursor(ast, 'add'|'remove')` 负责插入与移除该光标节点。渲染流程为:Markdown -> HTML -> htmlparser2 AST,然后将 AST 渲染为 Vue VNode。项目提供可选的模块 Worker(`public/parser.worker.js`)以将 Markdown 解析卸载到主线程之外。
13
-
14
- 本项目已配置为可发布的 npm 库(见 `package.json` 的脚本)。库从包根导出命名导出 `MdRenderer`(可通过 `import { MdRenderer } from 'mio-previewer'` 使用)。
18
+ ```bash
19
+ npm install mio-previewer
20
+ #
21
+ pnpm add mio-previewer
22
+ # 或
23
+ yarn add mio-previewer
24
+ ```
15
25
 
16
26
  ## 快速开始
17
27
 
18
- 先决条件:建议使用 Node 18+,以及 pnpm(或 npm/yarn)。
28
+ ### 基础用法
19
29
 
20
- 安装依赖:
30
+ ```vue
31
+ <template>
32
+ <MdRenderer :md="markdown" />
33
+ </template>
21
34
 
22
- ```bash
23
- pnpm install
35
+ <script setup>
36
+ import { ref } from 'vue'
37
+ import { MdRenderer } from 'mio-previewer'
38
+ import 'mio-previewer/dist/mio-previewer.css'
39
+
40
+ const markdown = ref('# Hello World\n\n这是 **Markdown** 渲染!')
41
+ </script>
24
42
  ```
25
43
 
26
- 本项目已配置为可发布的 npm 库(见 `package.json` 的脚本)。库从包根导出命名导出 `MdRenderer`(可通过 `import { MdRenderer } from 'mio-previewer'` 使用)。
44
+ ### 流式模式
27
45
 
28
- 启动开发服务器:
46
+ 适用于 AI 聊天机器人或实时内容展示:
29
47
 
30
- ```bash
31
- pnpm dev
48
+ ```vue
49
+ <template>
50
+ <MdRenderer
51
+ :md="streamContent"
52
+ :isStreaming="isStreaming"
53
+ />
54
+ </template>
55
+
56
+ <script setup>
57
+ import { ref } from 'vue'
58
+ import { MdRenderer } from 'mio-previewer'
59
+ import 'mio-previewer/dist/mio-previewer.css'
60
+
61
+ const streamContent = ref('')
62
+ const isStreaming = ref(true)
63
+
64
+ // 模拟流式输出
65
+ const text = '# 流式演示\n\n内容**逐步**出现...'
66
+ let index = 0
67
+
68
+ const interval = setInterval(() => {
69
+ if (index < text.length) {
70
+ streamContent.value += text[index++]
71
+ } else {
72
+ isStreaming.value = false
73
+ clearInterval(interval)
74
+ }
75
+ }, 50)
76
+ </script>
32
77
  ```
33
78
 
34
- 在浏览器打开 http://localhost:5173/ 以查看实时预览。
79
+ ## 插件系统
35
80
 
36
- 生产构建:
81
+ ### 使用内置插件
37
82
 
38
- ```bash
39
- pnpm build
40
- pnpm preview
83
+ #### 数学公式(KaTeX)
84
+
85
+ ```vue
86
+ <script setup>
87
+ import { MdRenderer } from 'mio-previewer'
88
+ import { katexPlugin } from 'mio-previewer/plugins/markdown-it'
89
+ import 'mio-previewer/dist/mio-previewer.css'
90
+
91
+ const markdown = \`
92
+ # 数学示例
93
+
94
+ 行内公式:$E = mc^2$
95
+
96
+ 块级公式:
97
+ $$
98
+ \\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}
99
+ $$
100
+ \`
101
+
102
+ const markdownItPlugins = [
103
+ { plugin: katexPlugin }
104
+ ]
105
+ </script>
106
+
107
+ <template>
108
+ <MdRenderer
109
+ :md="markdown"
110
+ :markdownItPlugins="markdownItPlugins"
111
+ />
112
+ </template>
41
113
  ```
42
114
 
43
- 安装库(发布后或本地安装):
115
+ #### 警告框
44
116
 
45
- ```bash
46
- # 从 npm 安装(发布后)
47
- pnpm add mio-previewer
117
+ ```vue
118
+ <script setup>
119
+ import { MdRenderer } from 'mio-previewer'
120
+ import { AlertPlugin } from 'mio-previewer/plugins/markdown-it'
121
+ import 'mio-previewer/dist/mio-previewer.css'
48
122
 
49
- # 或从本地目录安装
50
- pnpm add /path/to/mio-previewer
123
+ const markdown = \`
124
+ ::: info
125
+ 这是一个支持 **Markdown** 的 **info** 警告框!
126
+ :::
127
+
128
+ ::: warning
129
+ ⚠️ 警告信息
130
+ :::
131
+
132
+ ::: error
133
+ ❌ 错误信息
134
+ :::
135
+
136
+ ::: success
137
+ ✅ 成功信息
138
+ :::
139
+ \`
140
+
141
+ const markdownItPlugins = [
142
+ { plugin: AlertPlugin }
143
+ ]
144
+ </script>
145
+
146
+ <template>
147
+ <MdRenderer
148
+ :md="markdown"
149
+ :markdownItPlugins="markdownItPlugins"
150
+ />
151
+ </template>
51
152
  ```
52
153
 
53
- 使用示例(在 Vue 3 项目中):
154
+ #### 代码高亮
54
155
 
55
- ```js
56
- import { createApp } from 'vue'
156
+ ```vue
157
+ <script setup>
57
158
  import { MdRenderer } from 'mio-previewer'
58
- import 'github-markdown-css/github-markdown.css'
159
+ import { CodeBlockPlugin } from 'mio-previewer/plugins/custom'
160
+ import 'mio-previewer/dist/mio-previewer.css'
59
161
 
60
- const app = createApp({})
61
- app.component('MdRenderer', MdRenderer)
62
- app.mount('#app')
162
+ const markdown = \`
163
+ \\\`\\\`\\\`javascript
164
+ function hello() {
165
+ console.log('Hello World!')
166
+ }
167
+ \\\`\\\`\\\`
168
+
169
+ \\\`\\\`\\\`python
170
+ def greet():
171
+ print("你好,世界!")
172
+ \\\`\\\`\\\`
173
+ \`
174
+
175
+ const customPlugins = [CodeBlockPlugin]
176
+ </script>
177
+
178
+ <template>
179
+ <MdRenderer
180
+ :md="markdown"
181
+ :customPlugins="customPlugins"
182
+ />
183
+ </template>
63
184
  ```
64
185
 
65
- 注意事项
66
- - 库打包时将 `vue` 标记为 external。发布时建议在你的 `package.json` 中加入 `peerDependencies: { "vue": "^3" }`,或在宿主项目中安装兼容的 Vue。
67
- - 类型声明会输出到 `dist/types`,顶级 `types` 字段已指向生成的声明文件。
186
+ #### Mermaid 图表
68
187
 
69
- 发布清单
70
- - 确保 `package.json` 中包含 `name`、`version`、`description`、`repository` 等字段,并建议添加 `peerDependencies: { "vue": "^3" }`。
71
- - 运行 `pnpm run build`(会生成 bundle 和类型声明)。
72
- - 使用 `pnpm publish --access public` 发布,或在 CI 中自动化发布流程。
188
+ ```vue
189
+ <script setup>
190
+ import { MdRenderer } from 'mio-previewer'
191
+ import { mermaidPlugin } from 'mio-previewer/plugins/custom'
192
+ import 'mio-previewer/dist/mio-previewer.css'
193
+
194
+ const markdown = \`
195
+ \\\`\\\`\\\`mermaid
196
+ graph TD
197
+ A[开始] --> B{判断}
198
+ B -->|是| C[继续]
199
+ B -->|否| D[停止]
200
+ \\\`\\\`\\\`
201
+ \`
202
+
203
+ const customPlugins = [mermaidPlugin]
204
+ </script>
205
+
206
+ <template>
207
+ <MdRenderer
208
+ :md="markdown"
209
+ :customPlugins="customPlugins"
210
+ />
211
+ </template>
212
+ ```
73
213
 
74
- ## 项目概览
214
+ #### Emoji 表情
75
215
 
76
- - `src/MdRenderer.vue` — 核心组件。接收 `md`(字符串)、`isStreaming`(布尔)和 `useWorker`(布尔)三个 prop。负责解析、流式增量更新,以及在流式模式下管理特殊的光标组件节点。
77
- - `src/components/RecursiveRenderer.vue` — 将 htmlparser2 的 AST 递归渲染为 Vue VNode。支持 `plugins` 数组(每个 plugin 为 `{ test, render }`)。
78
- - `src/components/BlinkingCursor.vue` 流式渲染时显示的光标组件。
79
- - `public/parser.worker.js` —(可选)模块 Worker。当 `useWorker` 为 true 时,`MdRenderer` 会向 Worker 发送 `{ markdownText }` 并期望收到 `{ ast }`,其中 `ast` 的结构应与 `parseDocument(html).children` 一致。
216
+ ```vue
217
+ <script setup>
218
+ import { MdRenderer } from 'mio-previewer'
219
+ import { EmojiPlugin } from 'mio-previewer/plugins/custom'
220
+ import 'mio-previewer/dist/mio-previewer.css'
80
221
 
81
- ## 流式行为与光标管理
222
+ const markdown = '你好 :smile: 欢迎! :tada: :rocket:'
82
223
 
83
- 该项目支持两种模式:
224
+ const customPlugins = [EmojiPlugin]
225
+ </script>
84
226
 
85
- - 非流式(`isStreaming=false`):每次更新都会对 Markdown 进行全量解析。
86
- - 流式(`isStreaming=true`):对更新按增量块处理。`MdRenderer` 对简单纯文本块会尝试“追加到最后文本节点”的快速路径优化;若发现新块包含 Markdown 语法(例如 `#`, `` ` ``, `*` 等),则退回到重解析整串的安全路径。
227
+ <template>
228
+ <MdRenderer
229
+ :md="markdown"
230
+ :customPlugins="customPlugins"
231
+ />
232
+ </template>
233
+ ```
87
234
 
88
- 在流式模式下,代码会在 AST 末尾插入一个特殊节点 `{ type: 'component', name: 'cursor' }`,用于渲染 `BlinkingCursor`。辅助函数 `manageCursor(ast, 'add'|'remove')` 负责插入与移除该节点。
235
+ ### 完整示例(使用所有插件)
89
236
 
90
- ## 插件系统
237
+ ```vue
238
+ <script setup>
239
+ import { ref } from 'vue'
240
+ import { MdRenderer } from 'mio-previewer'
241
+ import { AlertPlugin, katexPlugin } from 'mio-previewer/plugins/markdown-it'
242
+ import { mermaidPlugin, CodeBlockPlugin, EmojiPlugin } from 'mio-previewer/plugins/custom'
243
+ import 'mio-previewer/dist/mio-previewer.css'
91
244
 
92
- mio-previewer 提供强大的双层插件系统:
245
+ const markdown = ref(\`# 完整演示 :rocket:
93
246
 
94
- ### 1. Markdown-it 插件(语法扩展)
247
+ ## 警告框
248
+ ::: info
249
+ 这是**重要**信息!
250
+ :::
95
251
 
96
- 通过标准 markdown-it 插件扩展 Markdown 语法:
252
+ ## 数学公式
253
+ 行内:$E = mc^2$
97
254
 
98
- ```js
99
- import { MdRenderer } from 'mio-previewer'
100
- import markdownItSub from 'markdown-it-sub'
101
- import markdownItSup from 'markdown-it-sup'
255
+ 块级:$$\\sum_{n=1}^{\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}$$
102
256
 
103
- const markdownItPlugins = [
104
- { plugin: markdownItSub },
105
- { plugin: markdownItSup, options: { /* 插件选项 */ } }
106
- ]
257
+ ## 代码
258
+ \\\`\\\`\\\`javascript
259
+ console.log('你好,世界!')
260
+ \\\`\\\`\\\`
107
261
 
108
- // 在组件中使用
109
- <MdRenderer
110
- :md="text"
111
- :markdownItPlugins="markdownItPlugins"
112
- :markdownItOptions="{ html: true, linkify: true }"
113
- />
114
- ```
262
+ ## 图表
263
+ \\\`\\\`\\\`mermaid
264
+ graph LR
265
+ A --> B --> C
266
+ \\\`\\\`\\\`
115
267
 
116
- ### 2. 自定义插件(渲染扩展)
268
+ 做得好! :thumbsup: :100:
269
+ \`)
117
270
 
118
- 为特定 AST 节点创建自定义渲染器:
271
+ const customPlugins = [
272
+ mermaidPlugin,
273
+ CodeBlockPlugin,
274
+ EmojiPlugin
275
+ ]
276
+
277
+ const markdownItPlugins = [
278
+ { plugin: AlertPlugin },
279
+ { plugin: katexPlugin }
280
+ ]
281
+ </script>
282
+
283
+ <template>
284
+ <MdRenderer
285
+ :md="markdown"
286
+ :customPlugins="customPlugins"
287
+ :markdownItPlugins="markdownItPlugins"
288
+ />
289
+ </template>
290
+ ```
119
291
 
120
- ```js
121
- import { AlertPlugin, EmojiPlugin } from 'mio-previewer'
292
+ ### 创建自定义插件
122
293
 
123
- // 内置插件
124
- const customPlugins = [AlertPlugin, EmojiPlugin]
294
+ #### 自定义渲染插件
125
295
 
126
- // 或创建自己的插件
127
- const MyPlugin = {
128
- name: 'my-plugin',
129
- priority: 50, // 更高优先级先执行
130
- test: (node) => node.type === 'tag' && node.name === 'custom',
296
+ ```javascript
297
+ const HighlightPlugin = {
298
+ name: 'highlight',
299
+ priority: 50,
300
+ test: (node) => {
301
+ return node.type === 'tag' &&
302
+ node.name === 'mark'
303
+ },
131
304
  render: (node, renderChildren, h) => {
132
- return h('div', { class: 'my-custom' }, renderChildren())
305
+ return h('mark', {
306
+ style: {
307
+ backgroundColor: '#ffeb3b',
308
+ padding: '2px 4px',
309
+ borderRadius: '2px'
310
+ }
311
+ }, renderChildren())
133
312
  }
134
313
  }
135
314
 
136
- <MdRenderer :md="text" :customPlugins="[MyPlugin, ...customPlugins]" />
315
+ // 使用插件
316
+ const customPlugins = [HighlightPlugin]
137
317
  ```
138
318
 
139
- ### 内置插件
319
+ #### 自定义 Markdown-it 插件
320
+
321
+ ```javascript
322
+ function customContainerPlugin(md) {
323
+ md.use(require('markdown-it-container'), 'note', {
324
+ render: (tokens, idx) => {
325
+ if (tokens[idx].nesting === 1) {
326
+ return '<div class="note">\n'
327
+ } else {
328
+ return '</div>\n'
329
+ }
330
+ }
331
+ })
332
+ }
140
333
 
141
- - **AlertPlugin**:渲染自定义警告框,支持类型(info、warning、error、success)
142
- - **EmojiPlugin**:将表情代码如 `:smile:` 转换为 😊
143
- - **CodeBlockPlugin**:使用 Prism 语法高亮,支持复制和 HTML 预览按钮(20+ 种语言)
144
- - **katexPlugin**:使用 KaTeX 渲染数学公式(支持 `$...$`、`$$...$$`、`\(...\)`、`\[...\]` 定界符)
145
- - **mermaidPlugin**:使用 Mermaid 渲染图表(流程图、时序图、状态图、类图等),支持深色/浅色主题
334
+ const markdownItPlugins = [
335
+ { plugin: customContainerPlugin }
336
+ ]
337
+ ```
146
338
 
147
- ### 插件优先级
339
+ ## API 参考
340
+
341
+ ### MdRenderer 属性
342
+
343
+ | 属性 | 类型 | 默认值 | 说明 |
344
+ |------|------|--------|------|
345
+ | \`md\` | \`string\` | \`''\` | 要渲染的 Markdown 内容 |
346
+ | \`isStreaming\` | \`boolean\` | \`false\` | 流式模式时显示光标 |
347
+ | \`useWorker\` | \`boolean\` | \`false\` | 使用 Web Worker 解析 |
348
+ | \`customPlugins\` | \`CustomPlugin[]\` | \`[]\` | 自定义渲染插件 |
349
+ | \`markdownItPlugins\` | \`MarkdownItPluginConfig[]\` | \`[]\` | Markdown-it 插件 |
350
+ | \`markdownItOptions\` | \`object\` | \`{}\` | Markdown-it 配置选项 |
351
+
352
+ ### 插件类型
353
+
354
+ #### CustomPlugin
355
+
356
+ ```typescript
357
+ interface CustomPlugin {
358
+ name?: string
359
+ priority?: number // 数字越大优先级越高
360
+ test: (node: ASTNode) => boolean
361
+ render: (
362
+ node: ASTNode,
363
+ renderChildren: () => VNode[],
364
+ h: typeof import('vue').h
365
+ ) => VNode | string | null
366
+ }
367
+ ```
148
368
 
149
- 插件按优先级顺序执行(优先级高的先执行)。内置 CursorPlugin 优先级为 100。
369
+ #### MarkdownItPluginConfig
150
370
 
151
- **推荐范围:**
152
- - 100+:系统插件
153
- - 50-99:高优先级(容器、警告框)
154
- - 10-49:中优先级(图标、徽章)
155
- - 0-9:低优先级(文本处理、表情)
371
+ ```typescript
372
+ interface MarkdownItPluginConfig {
373
+ plugin: (md: MarkdownIt, options?: any) => void
374
+ options?: any
375
+ }
376
+ ```
156
377
 
157
- ### 文档
378
+ ## 内置插件
158
379
 
159
- 详细文档、示例和最佳实践请参见 [插件指南](./docs/PLUGIN_GUIDE.md)。
380
+ ### Markdown-it 插件(语法)
160
381
 
161
- ### 演示
382
+ | 插件 | 导入路径 | 说明 |
383
+ |------|----------|------|
384
+ | \`AlertPlugin\` | \`mio-previewer/plugins/markdown-it\` | 警告框(info、warning、error、success)|
385
+ | \`katexPlugin\` | \`mio-previewer/plugins/markdown-it\` | KaTeX 数学公式 |
162
386
 
163
- 运行插件演示:
164
- ```bash
165
- pnpm dev
166
- # 打开 http://localhost:5173/plugin-demo.html
167
- ```
387
+ ### 自定义插件(渲染)
168
388
 
169
- ## Worker 合约
389
+ | 插件 | 导入路径 | 说明 |
390
+ |------|----------|------|
391
+ | \`mermaidPlugin\` | \`mio-previewer/plugins/custom\` | Mermaid 图表渲染 |
392
+ | \`CodeBlockPlugin\` | \`mio-previewer/plugins/custom\` | Prism 语法高亮 |
393
+ | \`EmojiPlugin\` | \`mio-previewer/plugins/custom\` | Emoji 代码替换 |
170
394
 
171
- `useWorker` 为 `true` 时,`MdRenderer` 会创建一个模块 Worker:
395
+ ## 高级用法
172
396
 
173
- ```js
174
- worker = new Worker(new URL('/parser.worker.js', import.meta.url), { type: 'module' })
175
- worker.postMessage({ markdownText: newMd })
176
- // worker 应返回: postMessage({ ast })
397
+ ### Markdown-it 配置
398
+
399
+ ```vue
400
+ <script setup>
401
+ const markdownItOptions = {
402
+ html: true, // 启用 HTML 标签
403
+ linkify: true, // 自动转换 URL
404
+ typographer: true, // 智能引号、破折号
405
+ breaks: false // 将 \n 转换为 <br>
406
+ }
407
+ </script>
408
+
409
+ <template>
410
+ <MdRenderer
411
+ :md="markdown"
412
+ :markdownItOptions="markdownItOptions"
413
+ />
414
+ </template>
177
415
  ```
178
416
 
179
- 返回的 `ast` 必须与 `parseDocument(html).children` 的结构保持一致,`RecursiveRenderer` 将直接消费该 AST。
417
+ ### Web Worker 模式
180
418
 
181
- ## TypeScript 迁移说明
419
+ 处理大文档时获得更好的性能:
182
420
 
183
- 项目已逐步迁移为 TypeScript 风格。为降低迁移风险,仓库中添加了临时的 `src/types-shims.d.ts` 用于最小化类型声明噪声。建议的下一步:
421
+ ```vue
422
+ <template>
423
+ <MdRenderer
424
+ :md="largeMarkdown"
425
+ :useWorker="true"
426
+ />
427
+ </template>
428
+ ```
429
+
430
+ **注意:** Worker 模式需要 \`public/parser.worker.js\` 文件可访问。
431
+
432
+ ## 开发
184
433
 
185
434
  ```bash
186
- pnpm add -D vue-tsc @types/htmlparser2 @types/markdown-it
187
- npx vue-tsc --noEmit
188
- ```
435
+ # 安装依赖
436
+ pnpm install
189
437
 
190
- 安装真实类型后,可删除临时 shim 并进行更严格的类型检查。
438
+ # 启动开发服务器
439
+ pnpm dev
191
440
 
192
- ## 开发建议
441
+ # 构建库
442
+ pnpm build
193
443
 
194
- - 如需调试 AST 输出,可在 `MdRenderer.vue` 中分配 `ast` 前打印 `parseDocument(html).children`,方便为插件设计节点匹配器。
195
- - 在更改流式逻辑时,注意调用 `manageCursor` 以在增量更新期间保持光标显示一致性。
444
+ # 运行基准测试
445
+ pnpm benchmark
446
+ ```
196
447
 
197
- ## 关注文件
448
+ ## 项目结构
198
449
 
199
- - `src/MdRenderer.vue` — 解析与流式逻辑
200
- - `src/components/RecursiveRenderer.vue` — 渲染器与插件系统
201
- - `src/components/BlinkingCursor.vue` — 用于流式的光标
202
- - `public/parser.worker.js` — 可选的 worker 解析契约
450
+ ```
451
+ mio-previewer/
452
+ ├── src/
453
+ │ ├── MdRenderer.vue # 主渲染器组件
454
+ │ ├── components/
455
+ │ │ ├── RecursiveRenderer.vue # AST 到 VNode 渲染器
456
+ │ │ ├── BlinkingCursor.vue # 流式光标
457
+ │ │ └── CodeBlock.vue # 代码高亮
458
+ │ ├── plugins/
459
+ │ │ ├── AlertPlugin.ts # 警告框
460
+ │ │ ├── katexPlugin.ts # 数学公式
461
+ │ │ ├── mermaidPlugin.ts # 图表
462
+ │ │ ├── CodeBlockPlugin.ts # 语法高亮
463
+ │ │ └── EmojiPlugin.ts # Emoji 支持
464
+ │ └── index.ts # 库入口
465
+ ├── public/
466
+ │ └── parser.worker.js # 可选 Web Worker
467
+ └── docs/ # 文档
468
+ ```
203
469
 
204
- ## License
470
+ ## 浏览器支持
471
+
472
+ - Chrome/Edge:最新 2 个版本
473
+ - Firefox:最新 2 个版本
474
+ - Safari:最新 2 个版本
475
+
476
+ ## 许可证
205
477
 
206
478
  MIT
479
+
480
+ ## 相关链接
481
+
482
+ - [GitHub 仓库](https://github.com/Pretend-to/mio-previewer)
483
+ - [npm 包](https://www.npmjs.com/package/mio-previewer)
484
+ - [插件指南](./docs/PLUGIN_GUIDE.md)
485
+ - [更新日志](./CHANGELOG.md)
@@ -0,0 +1,3 @@
1
+ "use strict";function $(a,i,l){function t(r){return r.trim().split(" ",2)[0]===i}function d(r,c,_,b,e){return r[c].nesting===1&&r[c].attrJoin("class",i),e.renderToken(r,c,_,b,e)}l=l||{};const p=3,u=l.marker||":",h=u.charCodeAt(0),f=u.length,A=l.validate||t,m=l.render||d;function C(r,c,_,b){let e,g=!1,n=r.bMarks[c]+r.tShift[c],s=r.eMarks[c];if(h!==r.src.charCodeAt(n))return!1;for(e=n+1;e<=s&&u[(e-n)%f]===r.src[e];e++);const x=Math.floor((e-n)/f);if(x<p)return!1;e-=(e-n)%f;const M=r.src.slice(n,e),v=r.src.slice(e,s);if(!A(v,M))return!1;if(b)return!0;let o=c;for(;o++,!(o>=_||(n=r.bMarks[o]+r.tShift[o],s=r.eMarks[o],n<s&&r.sCount[o]<r.blkIndent));)if(h===r.src.charCodeAt(n)&&!(r.sCount[o]-r.blkIndent>=4)){for(e=n+1;e<=s&&u[(e-n)%f]===r.src[e];e++);if(!(Math.floor((e-n)/f)<x)&&(e-=(e-n)%f,e=r.skipSpaces(e),!(e<s))){g=!0;break}}const T=r.parentType,S=r.lineMax;r.parentType="container",r.lineMax=o;const k=r.push("container_"+i+"_open","div",1);k.markup=M,k.block=!0,k.info=v,k.map=[c,o],r.md.block.tokenize(r,c+1,o);const y=r.push("container_"+i+"_close","div",-1);return y.markup=r.src.slice(n,e),y.block=!0,r.parentType=T,r.lineMax=S,r.line=o+(g?1:0),!0}a.block.ruler.before("fence","container_"+i,C,{alt:["paragraph","reference","blockquote","list"]}),a.renderer.rules["container_"+i+"_open"]=m,a.renderer.rules["container_"+i+"_close"]=m}function w(a){const i=["info","warning","error","success"],l={info:"#0ea5e9",warning:"#f59e0b",error:"#ef4444",success:"#10b981"};i.forEach(t=>{a.use($,t,{render:(d,p)=>{const u=l[t];return d[p].nesting===1?`<div class="custom-alert alert-${t}" style="padding: 12px 16px; border-left: 4px solid ${u}; background-color: ${u}15; margin: 8px 0; border-radius: 4px; font-family: system-ui, -apple-system, sans-serif;">
2
+ `:`</div>
3
+ `}})})}exports.AlertPlugin=w;
@@ -0,0 +1,66 @@
1
+ function $(s, i, l) {
2
+ function t(r) {
3
+ return r.trim().split(" ", 2)[0] === i;
4
+ }
5
+ function p(r, c, _, b, e) {
6
+ return r[c].nesting === 1 && r[c].attrJoin("class", i), e.renderToken(r, c, _, b, e);
7
+ }
8
+ l = l || {};
9
+ const d = 3, u = l.marker || ":", h = u.charCodeAt(0), f = u.length, A = l.validate || t, m = l.render || p;
10
+ function C(r, c, _, b) {
11
+ let e, g = !1, n = r.bMarks[c] + r.tShift[c], a = r.eMarks[c];
12
+ if (h !== r.src.charCodeAt(n))
13
+ return !1;
14
+ for (e = n + 1; e <= a && u[(e - n) % f] === r.src[e]; e++)
15
+ ;
16
+ const x = Math.floor((e - n) / f);
17
+ if (x < d)
18
+ return !1;
19
+ e -= (e - n) % f;
20
+ const M = r.src.slice(n, e), v = r.src.slice(e, a);
21
+ if (!A(v, M))
22
+ return !1;
23
+ if (b)
24
+ return !0;
25
+ let o = c;
26
+ for (; o++, !(o >= _ || (n = r.bMarks[o] + r.tShift[o], a = r.eMarks[o], n < a && r.sCount[o] < r.blkIndent)); )
27
+ if (h === r.src.charCodeAt(n) && !(r.sCount[o] - r.blkIndent >= 4)) {
28
+ for (e = n + 1; e <= a && u[(e - n) % f] === r.src[e]; e++)
29
+ ;
30
+ if (!(Math.floor((e - n) / f) < x) && (e -= (e - n) % f, e = r.skipSpaces(e), !(e < a))) {
31
+ g = !0;
32
+ break;
33
+ }
34
+ }
35
+ const T = r.parentType, S = r.lineMax;
36
+ r.parentType = "container", r.lineMax = o;
37
+ const k = r.push("container_" + i + "_open", "div", 1);
38
+ k.markup = M, k.block = !0, k.info = v, k.map = [c, o], r.md.block.tokenize(r, c + 1, o);
39
+ const y = r.push("container_" + i + "_close", "div", -1);
40
+ return y.markup = r.src.slice(n, e), y.block = !0, r.parentType = T, r.lineMax = S, r.line = o + (g ? 1 : 0), !0;
41
+ }
42
+ s.block.ruler.before("fence", "container_" + i, C, {
43
+ alt: ["paragraph", "reference", "blockquote", "list"]
44
+ }), s.renderer.rules["container_" + i + "_open"] = m, s.renderer.rules["container_" + i + "_close"] = m;
45
+ }
46
+ function w(s) {
47
+ const i = ["info", "warning", "error", "success"], l = {
48
+ info: "#0ea5e9",
49
+ warning: "#f59e0b",
50
+ error: "#ef4444",
51
+ success: "#10b981"
52
+ };
53
+ i.forEach((t) => {
54
+ s.use($, t, {
55
+ render: (p, d) => {
56
+ const u = l[t];
57
+ return p[d].nesting === 1 ? `<div class="custom-alert alert-${t}" style="padding: 12px 16px; border-left: 4px solid ${u}; background-color: ${u}15; margin: 8px 0; border-radius: 4px; font-family: system-ui, -apple-system, sans-serif;">
58
+ ` : `</div>
59
+ `;
60
+ }
61
+ });
62
+ });
63
+ }
64
+ export {
65
+ w as A
66
+ };