mio-previewer 0.1.1

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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +218 -0
  3. package/README.zh-CN.md +206 -0
  4. package/dist/MdRenderer.vue_vue_type_style_index_0_lang-ClzqKjX4.js +4562 -0
  5. package/dist/MdRenderer.vue_vue_type_style_index_0_lang-Dpnz3CdM.cjs +16 -0
  6. package/dist/_basePickBy-CZxbwAvt.cjs +1 -0
  7. package/dist/_basePickBy-nvL1-X4h.js +151 -0
  8. package/dist/_baseUniq-Cwhfu1XM.js +614 -0
  9. package/dist/_baseUniq-DunUk-cd.cjs +1 -0
  10. package/dist/_commonjsHelpers-DKOUU3wS.cjs +1 -0
  11. package/dist/_commonjsHelpers-DaMA6jEr.js +8 -0
  12. package/dist/_plugin-vue_export-helper-BHFhmbuH.cjs +1 -0
  13. package/dist/_plugin-vue_export-helper-CHgC5LLL.js +9 -0
  14. package/dist/arc-C9I4pYLv.js +83 -0
  15. package/dist/arc-fCflz0gB.cjs +1 -0
  16. package/dist/architecture-O4VJ6CD3-D00QJU0o.js +5 -0
  17. package/dist/architecture-O4VJ6CD3-dKuizgWO.cjs +1 -0
  18. package/dist/architectureDiagram-VXUJARFQ-DQ-YD3RX.cjs +36 -0
  19. package/dist/architectureDiagram-VXUJARFQ-VWr1UuPv.js +4662 -0
  20. package/dist/assets/parser.worker-67NQKZt5.js +16 -0
  21. package/dist/blockDiagram-VD42YOAC-DuC96I2Q.js +2261 -0
  22. package/dist/blockDiagram-VD42YOAC-EC2x5LwN.cjs +122 -0
  23. package/dist/c4Diagram-YG6GDRKO-Dm5d0BWL.cjs +10 -0
  24. package/dist/c4Diagram-YG6GDRKO-OB8wIuF8.js +1580 -0
  25. package/dist/channel-C-uR528Z.js +5 -0
  26. package/dist/channel-YfH5CBV-.cjs +1 -0
  27. package/dist/chunk-4BX2VUAB-3Liht_XN.cjs +1 -0
  28. package/dist/chunk-4BX2VUAB-j8LeaMvy.js +8 -0
  29. package/dist/chunk-55IACEB6-Dm3mi3ha.cjs +1 -0
  30. package/dist/chunk-55IACEB6-IYAIzfR4.js +8 -0
  31. package/dist/chunk-B4BG7PRW-CpqTB0S5.cjs +165 -0
  32. package/dist/chunk-B4BG7PRW-DB5df3Iz.js +1375 -0
  33. package/dist/chunk-DI55MBZ5-BoFZpvY3.js +1370 -0
  34. package/dist/chunk-DI55MBZ5-wqsoqtNw.cjs +220 -0
  35. package/dist/chunk-FMBD7UC4-BZS_4hun.cjs +15 -0
  36. package/dist/chunk-FMBD7UC4-CdmoYYnM.js +19 -0
  37. package/dist/chunk-QN33PNHL-BuyP9RXS.js +19 -0
  38. package/dist/chunk-QN33PNHL-CHI_-zix.cjs +1 -0
  39. package/dist/chunk-QZHKN3VN-15dJyQk0.js +15 -0
  40. package/dist/chunk-QZHKN3VN-DfH9qQ3T.cjs +1 -0
  41. package/dist/chunk-TZMSLE5B-BgFWf03M.js +64 -0
  42. package/dist/chunk-TZMSLE5B-qIo1h7Gz.cjs +1 -0
  43. package/dist/classDiagram-2ON5EDUG-BQz3UzKi.js +16 -0
  44. package/dist/classDiagram-2ON5EDUG-CZWeacVd.cjs +1 -0
  45. package/dist/classDiagram-v2-WZHVMYZB-BQz3UzKi.js +16 -0
  46. package/dist/classDiagram-v2-WZHVMYZB-CZWeacVd.cjs +1 -0
  47. package/dist/clone-ByeQKKoW.cjs +1 -0
  48. package/dist/clone-D6h_cwF4.js +8 -0
  49. package/dist/cose-bilkent-S5V4N54A-5dO3qpr4.cjs +1 -0
  50. package/dist/cose-bilkent-S5V4N54A-D2q7jBXB.js +2609 -0
  51. package/dist/cytoscape.esm-DHF7mANN.cjs +331 -0
  52. package/dist/cytoscape.esm-DfdJODL8.js +18735 -0
  53. package/dist/dagre-6UL2VRFP-Cfh4UdSr.js +444 -0
  54. package/dist/dagre-6UL2VRFP-DS2Ki9Dv.cjs +4 -0
  55. package/dist/defaultLocale-D7EN2tov.js +171 -0
  56. package/dist/defaultLocale-DIVzfLaQ.cjs +1 -0
  57. package/dist/diagram-PSM6KHXK-BZDEX43o.js +531 -0
  58. package/dist/diagram-PSM6KHXK-CTsP6f2a.cjs +24 -0
  59. package/dist/diagram-QEK2KX5R-BDKMNi97.cjs +43 -0
  60. package/dist/diagram-QEK2KX5R-Dda_FEDc.js +217 -0
  61. package/dist/diagram-S2PKOQOG-CmfsKOvs.cjs +24 -0
  62. package/dist/diagram-S2PKOQOG-Cnw4b7LB.js +142 -0
  63. package/dist/entries/md.cjs.js +1 -0
  64. package/dist/entries/md.es.js +5 -0
  65. package/dist/entries/plugin-alert.cjs.js +1 -0
  66. package/dist/entries/plugin-alert.es.js +27 -0
  67. package/dist/entries/plugin-codeblock.cjs.js +9 -0
  68. package/dist/entries/plugin-codeblock.es.js +3441 -0
  69. package/dist/entries/plugin-emoji.cjs.js +1 -0
  70. package/dist/entries/plugin-emoji.es.js +28 -0
  71. package/dist/entries/plugin-katex.cjs.js +1 -0
  72. package/dist/entries/plugin-katex.es.js +92 -0
  73. package/dist/entries/plugin-mermaid.cjs.js +1 -0
  74. package/dist/entries/plugin-mermaid.es.js +4 -0
  75. package/dist/erDiagram-Q2GNP2WA-DE4JLeNF.cjs +60 -0
  76. package/dist/erDiagram-Q2GNP2WA-qAdA8fbE.js +841 -0
  77. package/dist/favicon.ico +0 -0
  78. package/dist/flowDiagram-NV44I4VS-C7YBx4JP.js +1620 -0
  79. package/dist/flowDiagram-NV44I4VS-j3dB-fjF.cjs +162 -0
  80. package/dist/ganttDiagram-LVOFAZNH-BL-Yjadx.js +2506 -0
  81. package/dist/ganttDiagram-LVOFAZNH-CBhzET57.cjs +267 -0
  82. package/dist/gitGraph-ZV4HHKMB-Dr9sn7R3.js +5 -0
  83. package/dist/gitGraph-ZV4HHKMB-DyXW77WY.cjs +1 -0
  84. package/dist/gitGraphDiagram-NY62KEGX-DDklxVnY.cjs +65 -0
  85. package/dist/gitGraphDiagram-NY62KEGX-DFn7h5BH.js +699 -0
  86. package/dist/graph-CHoeKkVR.cjs +1 -0
  87. package/dist/graph-DiGqaw_6.js +247 -0
  88. package/dist/info-63CPKGFF-BGxbI0Qv.cjs +1 -0
  89. package/dist/info-63CPKGFF-xflgSxfH.js +5 -0
  90. package/dist/infoDiagram-F6ZHWCRC-DOtGa28U.js +24 -0
  91. package/dist/infoDiagram-F6ZHWCRC-Duylo4r7.cjs +2 -0
  92. package/dist/init-CHZsXQcr.cjs +1 -0
  93. package/dist/init-DjUOC4st.js +16 -0
  94. package/dist/journeyDiagram-XKPGCS4Q-bJncB3oe.js +834 -0
  95. package/dist/journeyDiagram-XKPGCS4Q-h-CtcfbS.cjs +139 -0
  96. package/dist/kanban-definition-3W4ZIXB7-C3y0C_bw.cjs +89 -0
  97. package/dist/kanban-definition-3W4ZIXB7-nMPCi8GW.js +719 -0
  98. package/dist/katex-CmGeg_OO.js +11692 -0
  99. package/dist/katex-DEiiRhcn.cjs +261 -0
  100. package/dist/layout-BG4AbhIW.cjs +1 -0
  101. package/dist/layout-CHaNS4g6.js +1324 -0
  102. package/dist/linear-Bqd4C_Yb.cjs +1 -0
  103. package/dist/linear-CPFNaVnw.js +259 -0
  104. package/dist/mermaid-parser.core-CR8Rcyps.cjs +128 -0
  105. package/dist/mermaid-parser.core-CkQKh-yb.js +12966 -0
  106. package/dist/mindmap-definition-VGOIOE7T-C63AEIdU.js +784 -0
  107. package/dist/mindmap-definition-VGOIOE7T-CHI9UFtA.cjs +68 -0
  108. package/dist/mio-previewer.cjs.js +3 -0
  109. package/dist/mio-previewer.css +1 -0
  110. package/dist/mio-previewer.es.js +25 -0
  111. package/dist/ordinal-CagbB1m8.cjs +1 -0
  112. package/dist/ordinal-DfAQgscy.js +61 -0
  113. package/dist/packet-HUATNLJX-BeAGxpDF.cjs +1 -0
  114. package/dist/packet-HUATNLJX-dnmrn2-l.js +5 -0
  115. package/dist/parser.worker.js +21 -0
  116. package/dist/pie-WTHONI2E-BKoHQt0i.js +5 -0
  117. package/dist/pie-WTHONI2E-BifrFKgo.cjs +1 -0
  118. package/dist/pieDiagram-ADFJNKIX-B9OONHi_.cjs +30 -0
  119. package/dist/pieDiagram-ADFJNKIX-CEMFAt9B.js +161 -0
  120. package/dist/plugin-mermaid-FTki7cN8.cjs +255 -0
  121. package/dist/plugin-mermaid-y4lbJ7sL.js +15369 -0
  122. package/dist/quadrantDiagram-AYHSOK5B-DobvzsAU.js +1022 -0
  123. package/dist/quadrantDiagram-AYHSOK5B-DqXDgyBD.cjs +7 -0
  124. package/dist/radar-NJJJXTRR-BPN19Spv.cjs +1 -0
  125. package/dist/radar-NJJJXTRR-Bj9rI8mr.js +5 -0
  126. package/dist/requirementDiagram-UZGBJVZJ-CVbmNF7M.cjs +64 -0
  127. package/dist/requirementDiagram-UZGBJVZJ-M-MPvTnX.js +850 -0
  128. package/dist/sankeyDiagram-TZEHDZUN-C-ESiLJA.cjs +10 -0
  129. package/dist/sankeyDiagram-TZEHDZUN-Czsin99f.js +810 -0
  130. package/dist/sequenceDiagram-WL72ISMW-BJByNQsK.js +2511 -0
  131. package/dist/sequenceDiagram-WL72ISMW-DApIQwP-.cjs +145 -0
  132. package/dist/stateDiagram-FKZM4ZOC-BuKL2w66.cjs +1 -0
  133. package/dist/stateDiagram-FKZM4ZOC-jAiBDhVn.js +263 -0
  134. package/dist/stateDiagram-v2-4FDKWEC3-Ct5PFxdd.cjs +1 -0
  135. package/dist/stateDiagram-v2-4FDKWEC3-umSVoFht.js +16 -0
  136. package/dist/timeline-definition-IT6M3QCI-BfAvK0gf.cjs +61 -0
  137. package/dist/timeline-definition-IT6M3QCI-I--lBLTi.js +795 -0
  138. package/dist/treemap-75Q7IDZK-DNt-zuL8.cjs +1 -0
  139. package/dist/treemap-75Q7IDZK-bjql9DgL.js +5 -0
  140. package/dist/types/entries/md.d.ts +3 -0
  141. package/dist/types/entries/plugin-alert.d.ts +1 -0
  142. package/dist/types/entries/plugin-codeblock.d.ts +1 -0
  143. package/dist/types/entries/plugin-emoji.d.ts +1 -0
  144. package/dist/types/entries/plugin-katex.d.ts +1 -0
  145. package/dist/types/entries/plugin-mermaid.d.ts +1 -0
  146. package/dist/types/helpers/containerHelpers.d.ts +47 -0
  147. package/dist/types/helpers/index.d.ts +4 -0
  148. package/dist/types/index.d.ts +5 -0
  149. package/dist/types/main-plugin-demo.d.ts +1 -0
  150. package/dist/types/main.d.ts +1 -0
  151. package/dist/types/plugins/AlertPlugin.d.ts +16 -0
  152. package/dist/types/plugins/CodeBlockPlugin.d.ts +9 -0
  153. package/dist/types/plugins/EmojiPlugin.d.ts +11 -0
  154. package/dist/types/plugins/katexPlugin.d.ts +8 -0
  155. package/dist/types/plugins/mermaidPlugin.d.ts +13 -0
  156. package/dist/types/types.d.ts +77 -0
  157. package/dist/xychartDiagram-PRI3JC2R-BN9e47xe.cjs +7 -0
  158. package/dist/xychartDiagram-PRI3JC2R-XrOK_egj.js +1340 -0
  159. package/package.json +114 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Mio-FCIP
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # mio-previewer
2
+
3
+ [中文文档](./README.zh-CN.md) | English
4
+
5
+ A small Vue 3 markdown previewer optimized for streaming updates. It
6
+ converts Markdown -> HTML -> htmlparser2 AST and renders the AST to Vue
7
+ VNode with a tiny recursive renderer. There's an optional module Worker
8
+ (`public/parser.worker.js`) that can handle Markdown parsing off the main
9
+
10
+ This project is also configured to be published as an npm library (see
11
+ `package.json` scripts). The library exposes a named export `MdRenderer`
12
+ from the package root (import { MdRenderer } from 'mio-previewer').
13
+ ## Quick start
14
+
15
+ Prerequisites: Node 18+ recommended, pnpm (or npm/yarn).
16
+
17
+ Install dependencies:
18
+
19
+ ```bash
20
+ pnpm install
21
+ ```
22
+
23
+ Run dev server:
24
+
25
+ ```bash
26
+ pnpm dev
27
+ ```
28
+
29
+ Open http://localhost:5173/ to view the live preview.
30
+
31
+ Build for production:
32
+
33
+ ```bash
34
+ pnpm build
35
+ pnpm preview
36
+ ```
37
+
38
+ Install the package (after publishing or using a local install):
39
+
40
+ ```bash
41
+ # from npm (when published)
42
+ pnpm add mio-previewer
43
+
44
+ # or install from a local folder
45
+ pnpm add /path/to/mio-previewer
46
+ ```
47
+
48
+ Usage example (consumer project with Vue 3):
49
+
50
+ ```js
51
+ import { createApp } from 'vue'
52
+ import { MdRenderer } from 'mio-previewer'
53
+ import 'github-markdown-css/github-markdown.css'
54
+
55
+ const app = createApp({})
56
+ app.component('MdRenderer', MdRenderer)
57
+ app.mount('#app')
58
+ ```
59
+
60
+ Notes for bundlers and consumers
61
+ - `vue` is marked as external in the library bundle. Add `vue@^3` to
62
+ your project's dependencies (or peerDependencies) when publishing.
63
+ - Types are emitted to `dist/types` during build; the package `types`
64
+ field points to the generated declaration file.
65
+
66
+ Publishing checklist
67
+ - Ensure `package.json` has `name`, `version`, `description`, `repository`,
68
+ and `peerDependencies: { "vue": "^3" }` (recommended).
69
+ - Run `pnpm run build` (this runs the lib build and emits types).
70
+ - Publish with `pnpm publish --access public` (or use CI automation).
71
+ ## Project overview
72
+
73
+ - `src/MdRenderer.vue` — core component. Accepts props `md` (string),
74
+ `isStreaming` (boolean) and `useWorker` (boolean). Handles parsing,
75
+ streaming-friendly incremental updates, and manages a special cursor
76
+ component node while streaming.
77
+ - `src/components/RecursiveRenderer.vue` — recursively renders the
78
+ htmlparser2 AST to Vue VNodes. Supports a `plugins` array where each
79
+ plugin is `{ test, render }`.
80
+ - `src/components/BlinkingCursor.vue` — small visual cursor used during
81
+ streaming.
82
+ - `public/parser.worker.js` — (optional) module Worker. When enabled
83
+ (`useWorker`), `MdRenderer` posts `{ markdownText }` and expects a
84
+ response `{ ast }` where `ast` matches `parseDocument(html).children`.
85
+
86
+ ## Streaming behavior and cursor management
87
+
88
+ The `isStreaming` prop controls whether a blinking cursor is displayed at the end of the rendered content:
89
+
90
+ - `isStreaming=false` — No cursor is shown. Use this for static content or when streaming has finished.
91
+ - `isStreaming=true` — A blinking cursor is displayed at the end, indicating that content is actively streaming/updating.
92
+
93
+ When `isStreaming` is `true`, a special AST node `{ type: 'component', name: 'cursor' }` is inserted at the end of the AST to render the `BlinkingCursor` component. The helper `manageCursor(ast, 'add'|'remove')` handles insertion/removal of this cursor node.
94
+
95
+ ## Plugin System
96
+
97
+ mio-previewer provides a powerful two-tier plugin system:
98
+
99
+ ### 1. Markdown-it Plugins (Syntax Extension)
100
+
101
+ Extend Markdown syntax by using standard markdown-it plugins:
102
+
103
+ ```js
104
+ import { MdRenderer } from 'mio-previewer'
105
+ import markdownItSub from 'markdown-it-sub'
106
+ import markdownItSup from 'markdown-it-sup'
107
+
108
+ const markdownItPlugins = [
109
+ { plugin: markdownItSub },
110
+ { plugin: markdownItSup, options: { /* plugin options */ } }
111
+ ]
112
+
113
+ // Use in component
114
+ <MdRenderer
115
+ :md="text"
116
+ :markdownItPlugins="markdownItPlugins"
117
+ :markdownItOptions="{ html: true, linkify: true }"
118
+ />
119
+ ```
120
+
121
+ ### 2. Custom Plugins (Rendering Extension)
122
+
123
+ Create custom renderers for specific AST nodes:
124
+
125
+ ```js
126
+ import { AlertPlugin, EmojiPlugin } from 'mio-previewer'
127
+
128
+ // Built-in plugins
129
+ const customPlugins = [AlertPlugin, EmojiPlugin]
130
+
131
+ // Or create your own
132
+ const MyPlugin = {
133
+ name: 'my-plugin',
134
+ priority: 50, // Higher priority executes first
135
+ test: (node) => node.type === 'tag' && node.name === 'custom',
136
+ render: (node, renderChildren, h) => {
137
+ return h('div', { class: 'my-custom' }, renderChildren())
138
+ }
139
+ }
140
+
141
+ <MdRenderer :md="text" :customPlugins="[MyPlugin, ...customPlugins]" />
142
+ ```
143
+
144
+ ### Built-in Plugins
145
+
146
+ - **AlertPlugin**: Renders custom alert boxes with types (info, warning, error, success)
147
+ - **EmojiPlugin**: Converts emoji codes like `:smile:` → 😊
148
+ - **CodeBlockPlugin**: Prism syntax highlighting with copy & HTML preview buttons (20+ languages)
149
+ - **katexPlugin**: Renders math formulas with KaTeX (supports `$...$`, `$$...$$`, `\(...\)`, `\[...\]` delimiters)
150
+ - **mermaidPlugin**: Renders diagrams with Mermaid (flowcharts, sequence diagrams, state diagrams, class diagrams, etc.) with dark/light theme support
151
+
152
+ ### Plugin Priority
153
+
154
+ Plugins are executed in priority order (higher first). Built-in CursorPlugin has priority 100.
155
+
156
+ **Recommended ranges:**
157
+ - 100+: System plugins
158
+ - 50-99: High priority (containers, alerts)
159
+ - 10-49: Medium priority (icons, badges)
160
+ - 0-9: Low priority (text processing, emoji)
161
+
162
+ ### Documentation
163
+
164
+ See [Plugin Guide](./docs/PLUGIN_GUIDE.md) for detailed documentation, examples, and best practices.
165
+
166
+ ### Demo
167
+
168
+ Run the plugin demo:
169
+ ```bash
170
+ pnpm dev
171
+ # Open http://localhost:5173/plugin-demo.html
172
+ ```
173
+
174
+ ## Worker contract
175
+
176
+ When `useWorker` is `true`, `MdRenderer` creates a module Worker with:
177
+
178
+ ```js
179
+ worker = new Worker(new URL('/parser.worker.js', import.meta.url), { type: 'module' })
180
+ worker.postMessage({ markdownText: newMd })
181
+ // worker should respond with: postMessage({ ast })
182
+ ```
183
+
184
+ The `ast` must be the same shape as `parseDocument(html).children` so
185
+ that `RecursiveRenderer` can consume it directly.
186
+
187
+ ## TypeScript migration notes
188
+
189
+ This repo was migrated progressively to TypeScript. To keep the
190
+ conversion low-risk, a temporary `src/types-shims.d.ts` provides minimal
191
+ module declarations. Recommended next steps to tighten types:
192
+
193
+ ```bash
194
+ pnpm add -D vue-tsc @types/htmlparser2 @types/markdown-it
195
+ npx vue-tsc --noEmit
196
+ ```
197
+
198
+ Then replace the shim declarations with real types from the installed
199
+ packages.
200
+
201
+ ## Development tips
202
+
203
+ - To debug AST output, add a `console.log(parseDocument(html).children)`
204
+ in `MdRenderer.vue` before assigning `ast` — this helps inspect node
205
+ shapes for plugin writing.
206
+ - If you change streaming logic, ensure `manageCursor` is called to
207
+ preserve cursor visibility during incremental updates.
208
+
209
+ ## Files of interest
210
+
211
+ - `src/MdRenderer.vue` — main parsing & streaming logic
212
+ - `src/components/RecursiveRenderer.vue` — renderer & plugin system
213
+ - `src/components/BlinkingCursor.vue` — streaming cursor
214
+ - `public/parser.worker.js` — optional worker parsing contract
215
+
216
+ ## License
217
+
218
+ MIT
@@ -0,0 +1,206 @@
1
+ # mio-previewer
2
+
3
+ [English](./README.md) | 中文文档
4
+
5
+ 一个针对流式更新优化的小型 Vue 3 Markd## 流式行为与光标管理
6
+
7
+ `isStreaming` prop 控制是否在渲染内容末尾显示闪烁的光标:
8
+
9
+ - `isStreaming=false` — 不显示光标。用于静态内容或流式更新已结束的情况。
10
+ - `isStreaming=true` — 在末尾显示闪烁光标,表示内容正在流式更新中。
11
+
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'` 使用)。
15
+
16
+ ## 快速开始
17
+
18
+ 先决条件:建议使用 Node 18+,以及 pnpm(或 npm/yarn)。
19
+
20
+ 安装依赖:
21
+
22
+ ```bash
23
+ pnpm install
24
+ ```
25
+
26
+ 本项目已配置为可发布的 npm 库(见 `package.json` 的脚本)。库从包根导出命名导出 `MdRenderer`(可通过 `import { MdRenderer } from 'mio-previewer'` 使用)。
27
+
28
+ 启动开发服务器:
29
+
30
+ ```bash
31
+ pnpm dev
32
+ ```
33
+
34
+ 在浏览器打开 http://localhost:5173/ 以查看实时预览。
35
+
36
+ 生产构建:
37
+
38
+ ```bash
39
+ pnpm build
40
+ pnpm preview
41
+ ```
42
+
43
+ 安装库(发布后或本地安装):
44
+
45
+ ```bash
46
+ # 从 npm 安装(发布后)
47
+ pnpm add mio-previewer
48
+
49
+ # 或从本地目录安装
50
+ pnpm add /path/to/mio-previewer
51
+ ```
52
+
53
+ 使用示例(在 Vue 3 项目中):
54
+
55
+ ```js
56
+ import { createApp } from 'vue'
57
+ import { MdRenderer } from 'mio-previewer'
58
+ import 'github-markdown-css/github-markdown.css'
59
+
60
+ const app = createApp({})
61
+ app.component('MdRenderer', MdRenderer)
62
+ app.mount('#app')
63
+ ```
64
+
65
+ 注意事项
66
+ - 库打包时将 `vue` 标记为 external。发布时建议在你的 `package.json` 中加入 `peerDependencies: { "vue": "^3" }`,或在宿主项目中安装兼容的 Vue。
67
+ - 类型声明会输出到 `dist/types`,顶级 `types` 字段已指向生成的声明文件。
68
+
69
+ 发布清单
70
+ - 确保 `package.json` 中包含 `name`、`version`、`description`、`repository` 等字段,并建议添加 `peerDependencies: { "vue": "^3" }`。
71
+ - 运行 `pnpm run build`(会生成 bundle 和类型声明)。
72
+ - 使用 `pnpm publish --access public` 发布,或在 CI 中自动化发布流程。
73
+
74
+ ## 项目概览
75
+
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` 一致。
80
+
81
+ ## 流式行为与光标管理
82
+
83
+ 该项目支持两种模式:
84
+
85
+ - 非流式(`isStreaming=false`):每次更新都会对 Markdown 进行全量解析。
86
+ - 流式(`isStreaming=true`):对更新按增量块处理。`MdRenderer` 对简单纯文本块会尝试“追加到最后文本节点”的快速路径优化;若发现新块包含 Markdown 语法(例如 `#`, `` ` ``, `*` 等),则退回到重解析整串的安全路径。
87
+
88
+ 在流式模式下,代码会在 AST 末尾插入一个特殊节点 `{ type: 'component', name: 'cursor' }`,用于渲染 `BlinkingCursor`。辅助函数 `manageCursor(ast, 'add'|'remove')` 负责插入与移除该节点。
89
+
90
+ ## 插件系统
91
+
92
+ mio-previewer 提供强大的双层插件系统:
93
+
94
+ ### 1. Markdown-it 插件(语法扩展)
95
+
96
+ 通过标准 markdown-it 插件扩展 Markdown 语法:
97
+
98
+ ```js
99
+ import { MdRenderer } from 'mio-previewer'
100
+ import markdownItSub from 'markdown-it-sub'
101
+ import markdownItSup from 'markdown-it-sup'
102
+
103
+ const markdownItPlugins = [
104
+ { plugin: markdownItSub },
105
+ { plugin: markdownItSup, options: { /* 插件选项 */ } }
106
+ ]
107
+
108
+ // 在组件中使用
109
+ <MdRenderer
110
+ :md="text"
111
+ :markdownItPlugins="markdownItPlugins"
112
+ :markdownItOptions="{ html: true, linkify: true }"
113
+ />
114
+ ```
115
+
116
+ ### 2. 自定义插件(渲染扩展)
117
+
118
+ 为特定 AST 节点创建自定义渲染器:
119
+
120
+ ```js
121
+ import { AlertPlugin, EmojiPlugin } from 'mio-previewer'
122
+
123
+ // 内置插件
124
+ const customPlugins = [AlertPlugin, EmojiPlugin]
125
+
126
+ // 或创建自己的插件
127
+ const MyPlugin = {
128
+ name: 'my-plugin',
129
+ priority: 50, // 更高优先级先执行
130
+ test: (node) => node.type === 'tag' && node.name === 'custom',
131
+ render: (node, renderChildren, h) => {
132
+ return h('div', { class: 'my-custom' }, renderChildren())
133
+ }
134
+ }
135
+
136
+ <MdRenderer :md="text" :customPlugins="[MyPlugin, ...customPlugins]" />
137
+ ```
138
+
139
+ ### 内置插件
140
+
141
+ - **AlertPlugin**:渲染自定义警告框,支持类型(info、warning、error、success)
142
+ - **EmojiPlugin**:将表情代码如 `:smile:` 转换为 😊
143
+ - **CodeBlockPlugin**:使用 Prism 语法高亮,支持复制和 HTML 预览按钮(20+ 种语言)
144
+ - **katexPlugin**:使用 KaTeX 渲染数学公式(支持 `$...$`、`$$...$$`、`\(...\)`、`\[...\]` 定界符)
145
+ - **mermaidPlugin**:使用 Mermaid 渲染图表(流程图、时序图、状态图、类图等),支持深色/浅色主题
146
+
147
+ ### 插件优先级
148
+
149
+ 插件按优先级顺序执行(优先级高的先执行)。内置 CursorPlugin 优先级为 100。
150
+
151
+ **推荐范围:**
152
+ - 100+:系统插件
153
+ - 50-99:高优先级(容器、警告框)
154
+ - 10-49:中优先级(图标、徽章)
155
+ - 0-9:低优先级(文本处理、表情)
156
+
157
+ ### 文档
158
+
159
+ 详细文档、示例和最佳实践请参见 [插件指南](./docs/PLUGIN_GUIDE.md)。
160
+
161
+ ### 演示
162
+
163
+ 运行插件演示:
164
+ ```bash
165
+ pnpm dev
166
+ # 打开 http://localhost:5173/plugin-demo.html
167
+ ```
168
+
169
+ ## Worker 合约
170
+
171
+ 当 `useWorker` 为 `true` 时,`MdRenderer` 会创建一个模块 Worker:
172
+
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 })
177
+ ```
178
+
179
+ 返回的 `ast` 必须与 `parseDocument(html).children` 的结构保持一致,`RecursiveRenderer` 将直接消费该 AST。
180
+
181
+ ## TypeScript 迁移说明
182
+
183
+ 项目已逐步迁移为 TypeScript 风格。为降低迁移风险,仓库中添加了临时的 `src/types-shims.d.ts` 用于最小化类型声明噪声。建议的下一步:
184
+
185
+ ```bash
186
+ pnpm add -D vue-tsc @types/htmlparser2 @types/markdown-it
187
+ npx vue-tsc --noEmit
188
+ ```
189
+
190
+ 安装真实类型后,可删除临时 shim 并进行更严格的类型检查。
191
+
192
+ ## 开发建议
193
+
194
+ - 如需调试 AST 输出,可在 `MdRenderer.vue` 中分配 `ast` 前打印 `parseDocument(html).children`,方便为插件设计节点匹配器。
195
+ - 在更改流式逻辑时,注意调用 `manageCursor` 以在增量更新期间保持光标显示一致性。
196
+
197
+ ## 关注文件
198
+
199
+ - `src/MdRenderer.vue` — 解析与流式逻辑
200
+ - `src/components/RecursiveRenderer.vue` — 渲染器与插件系统
201
+ - `src/components/BlinkingCursor.vue` — 用于流式的光标
202
+ - `public/parser.worker.js` — 可选的 worker 解析契约
203
+
204
+ ## License
205
+
206
+ MIT