md2ui 1.0.19 → 1.0.20

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 (29) hide show
  1. package/README.md +65 -20
  2. package/bin/build.js +13 -2
  3. package/bin/md2ui.js +25 -12
  4. package/package.json +2 -2
  5. package/public/docs/02-Markdown/346/270/262/346/237/223/00-/345/237/272/347/241/200/350/257/255/346/263/225.md +2 -0
  6. package/public/docs/02-Markdown/346/270/262/346/237/223/06-Mermaid/345/244/215/346/235/202/345/233/276/350/241/250/346/265/213/350/257/225.md +1376 -0
  7. package/public/docs/02-Markdown/346/270/262/346/237/223/assets/img-1777383093712.png +0 -0
  8. package/public/docs/03-/345/257/274/350/210/252/344/270/216/345/270/203/345/261/200/05-/345/244/247/347/272/262/345/216/213/345/212/233/346/265/213/350/257/225.md +340 -0
  9. package/public/docs/07-/347/247/273/345/212/250/347/253/257/351/200/202/351/205/215/00-/345/223/215/345/272/224/345/274/217/345/270/203/345/261/200.md +4 -4
  10. package/src/App.vue +36 -61
  11. package/src/components/ImageZoom.vue +9 -123
  12. package/src/components/MermaidNodeView.vue +10 -2
  13. package/src/components/MobileSearch.vue +97 -0
  14. package/src/components/TableOfContents.vue +42 -6
  15. package/src/composables/useDocManager.js +134 -44
  16. package/src/composables/useDocTree.js +26 -50
  17. package/src/composables/useMarkdown.js +51 -140
  18. package/src/composables/useMermaidCache.js +15 -0
  19. package/src/composables/useScroll.js +317 -32
  20. package/src/composables/useSearch.js +12 -11
  21. package/src/config.js +1 -4
  22. package/src/services/DocService.js +0 -16
  23. package/src/style.css +235 -10
  24. package/src/utils/imageConverter.js +129 -0
  25. package/vite-plugin-doc-api.js +158 -157
  26. package/vite.config.js +5 -1
  27. package/src/components/SearchPanel.vue +0 -90
  28. package/src/components/TableBubbleMenu.vue +0 -177
  29. package/src/composables/useExportPdf.js +0 -102
package/README.md CHANGED
@@ -4,27 +4,72 @@
4
4
  [![GitHub](https://img.shields.io/badge/GitHub-xiaoyaodev%2Fmd2ui-blue?logo=github)](https://github.com/xiaoyaodev/md2ui)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
6
6
 
7
- 一个轻量级的 Markdown 文档渲染工具,将本地 `.md` 文件转换为美观的 HTML 页面。支持实时预览和静态站点生成(SSG)两种模式。
7
+ 轻量级 Markdown 文档站点工具,一行命令将本地 `.md` 文件转换为可预览、可编辑、可搜索的文档站点。
8
8
 
9
- ## 功能特性
9
+ ## 为什么需要 md2ui?
10
10
 
11
- - 自动目录树 - 扫描文档文件夹,自动生成多级导航,支持搜索过滤
12
- - 三栏布局 - 左侧导航 / 中间内容 / 右侧大纲,可拖拽调整宽度
13
- - Markdown 增强 - GFM 语法、代码高亮、Mermaid 图表、Frontmatter
14
- - 全文搜索 - 基于 MiniSearch 的快速全文检索
15
- - 移动端适配 - 响应式布局,抽屉式导航和目录
16
- - 阅读体验 - 阅读进度条、预计阅读时间、上下篇导航
17
- - SSG 构建 - `md2ui build` 生成纯静态 HTML,可直接部署
11
+ AI 编程时代,Cursor、Copilot、Kiro 等工具正在改变我们的开发方式。与 AI 协作的过程中,会产生大量的 Markdown 文档 —— 需求文档、设计方案、API 文档、会议纪要、技术调研……
12
+
13
+ 这些 `.md` 文件散落在项目各处,带来了一系列痛点:
14
+
15
+ - 文件越来越多,找一篇文档要翻半天
16
+ - IDE Markdown 预览体验一般,表格、流程图、数学公式渲染不理想
17
+ - 想快速改几个字,还得切回编辑器找到对应文件
18
+ - 文档之间缺乏导航关系,无法形成知识体系
19
+ - 想分享给团队成员,还得额外搭建文档站
20
+
21
+ md2ui 就是为了解决这些问题而生的。把它指向你的文档目录,立刻获得一个功能完整的文档站点。
22
+
23
+ ## 核心能力
24
+
25
+ - 零配置启动 - `cd docs && md2ui`,开箱即用
26
+ - 实时预览 - 文件变更自动刷新,所见即所得
27
+ - 在线编辑 - 内置富文本编辑器,直接在浏览器中修改并保存到本地文件
28
+ - 全文搜索 - 基于 MiniSearch,毫秒级检索所有文档内容
29
+ - 自动导航 - 扫描目录结构自动生成多级目录树,支持拖拽排序
30
+ - 三栏布局 - 左侧导航 / 中间内容 / 右侧大纲,宽度可拖拽调整
31
+ - Markdown 增强 - GFM 语法、代码高亮、Mermaid 图表、数学公式、Frontmatter
32
+ - 移动端适配 - 响应式布局,手机上也能舒适阅读
33
+ - 阅读体验 - 进度条、预计阅读时间、上下篇导航、图片放大
34
+ - SSG 构建 - `md2ui build` 生成纯静态站点,可直接部署
18
35
  - 自定义配置 - 站点标题、主题色、GitHub 链接、页脚等
19
36
 
20
- ## 安装使用
37
+ ## 界面预览
38
+ 预览模式
39
+ ![预览模式](imgs/1.png)
40
+ 编辑模式
41
+
42
+ ![编辑模式](imgs/2.png)
43
+
44
+ ## 典型使用场景
45
+
46
+ **AI 辅助开发的文档管理**
47
+
48
+ 用 AI 生成的需求文档、设计方案、技术调研统一放到一个目录,md2ui 提供即时预览和编辑,让文档真正流动起来。
49
+
50
+ **个人知识库**
21
51
 
22
- ### 全局安装
52
+ 日常笔记、学习记录、读书摘要,用 Markdown 写完丢进文件夹,md2ui 自动组织成可浏览的知识站点。
53
+
54
+ **项目文档站**
55
+
56
+ API 文档、部署指南、开发规范,`md2ui build` 一键构建为静态站点,部署到任意服务器。
57
+
58
+ **团队协作文档**
59
+
60
+ 配合 Git 管理文档版本,本地用 md2ui 预览和编辑,提交后自动构建部署。
61
+
62
+ ## 快速开始
63
+
64
+ ### 安装
23
65
 
24
66
  ```bash
25
- pnpm add -g md2ui
26
- # 或
67
+ # 需要提前安装nodejs运行环境
27
68
  npm install -g md2ui
69
+
70
+
71
+ # 免安装 一次性运行
72
+ npx md2ui
28
73
  ```
29
74
 
30
75
  ### 实时预览
@@ -36,21 +81,19 @@ cd /path/to/your/docs
36
81
  md2ui
37
82
  ```
38
83
 
39
- 指定端口:
84
+ 访问 http://localhost:3000 即可查看文档。支持 `-p` 参数指定端口:
40
85
 
41
86
  ```bash
42
87
  md2ui -p 8080
43
88
  ```
44
89
 
45
- 访问 http://localhost:3000 查看文档(默认端口 3000)。
46
-
47
90
  ### 静态构建
48
91
 
49
92
  ```bash
50
93
  md2ui build
51
94
  ```
52
95
 
53
- 生成的静态文件在 `dist/` 目录下,可直接部署到任意静态服务器。
96
+ 生成的静态文件在 `dist/` 目录下,可直接部署到 Nginx、GitHub Pages、Vercel 等任意静态托管服务。
54
97
 
55
98
  ## 文档组织
56
99
 
@@ -65,8 +108,8 @@ your-docs/
65
108
  ```
66
109
 
67
110
  - 使用 `序号-名称.md` 格式控制排序,如 `01-快速开始.md`
68
- - 文件夹也支持序号前缀,如 `02-进阶指南/`
69
- - 序号越小越靠前
111
+ - 文件夹同样支持序号前缀,如 `02-进阶指南/`
112
+ - 支持任意层级嵌套
70
113
 
71
114
  ## 自定义配置
72
115
 
@@ -79,7 +122,7 @@ export default {
79
122
  port: 8080,
80
123
  folderExpanded: true,
81
124
  themeColor: '#3eaf7c',
82
- github: 'https://github.com/xiaoyaodev/md2ui',
125
+ github: 'https://github.com/your/repo',
83
126
  footer: 'Copyright © 2025'
84
127
  }
85
128
  ```
@@ -113,6 +156,8 @@ md2ui/
113
156
  │ ├── App.vue # 主组件
114
157
  │ ├── components/ # Vue 组件
115
158
  │ ├── composables/ # 组合式函数
159
+ │ ├── extensions/ # Tiptap 编辑器扩展
160
+ │ ├── services/ # 文档服务
116
161
  │ ├── config.js # 共享配置
117
162
  │ └── style.css # 全局样式
118
163
  ├── public/docs/ # 示例文档
package/bin/build.js CHANGED
@@ -574,8 +574,19 @@ function getSsgCss(pkgRoot) {
574
574
 
575
575
  // ===== 主构建流程 =====
576
576
  async function build() {
577
+ // 解析位置参数:md2ui build [dir]
578
+ const args = process.argv.slice(3)
579
+ let targetDir = null
580
+ for (const arg of args) {
581
+ if (!arg.startsWith('-')) {
582
+ targetDir = arg
583
+ break
584
+ }
585
+ }
586
+ const scanDir = targetDir ? resolve(userDir, targetDir) : userDir
587
+
577
588
  console.log('\n md2ui build - 静态站点生成\n')
578
- console.log(` 扫描目录: ${userDir}\n`)
589
+ console.log(` 扫描目录: ${scanDir}\n`)
579
590
 
580
591
  // 加载配置
581
592
  const userConfig = await loadUserConfig()
@@ -583,7 +594,7 @@ async function build() {
583
594
  const outDir = resolve(userDir, siteConfig.outDir || 'dist')
584
595
 
585
596
  // 扫描文档
586
- const docsList = scanDocs(userDir, '', 0, siteConfig.folderExpanded)
597
+ const docsList = scanDocs(scanDir, '', 0, siteConfig.folderExpanded)
587
598
  const flatDocs = flattenDocs(docsList)
588
599
 
589
600
  if (flatDocs.length === 0) {
package/bin/md2ui.js CHANGED
@@ -63,11 +63,14 @@ async function loadUserConfig() {
63
63
  // 解析命令行参数
64
64
  function parseArgs() {
65
65
  const args = process.argv.slice(2)
66
- const result = {}
66
+ const result = { dir: null }
67
67
  for (let i = 0; i < args.length; i++) {
68
68
  if (args[i] === '-p' || args[i] === '--port') {
69
69
  result.port = parseInt(args[i + 1]) || undefined
70
70
  i++
71
+ } else if (!args[i].startsWith('-')) {
72
+ // 位置参数作为扫描目录
73
+ result.dir = args[i]
71
74
  }
72
75
  }
73
76
  return result
@@ -131,7 +134,7 @@ function hasMdFiles(dir) {
131
134
  }
132
135
 
133
136
  // Vite 插件:提供用户文档 API + 配置 API + 热更新
134
- function md2uiPlugin(siteConfig) {
137
+ function md2uiPlugin(siteConfig, docsRoot) {
135
138
  return {
136
139
  name: 'md2ui-server',
137
140
  configureServer(server) {
@@ -139,7 +142,7 @@ function md2uiPlugin(siteConfig) {
139
142
  server.middlewares.use((req, res, next) => {
140
143
  // 文档列表 API(带 ETag 支持,避免轮询时重复传输)
141
144
  if (req.url === '/@user-docs-list') {
142
- const docs = scanDocs(userDir, '', 0, siteConfig.folderExpanded)
145
+ const docs = scanDocs(docsRoot, '', 0, siteConfig.folderExpanded)
143
146
  const body = JSON.stringify(docs)
144
147
  const etag = '"' + crypto.createHash('md5').update(body).digest('hex') + '"'
145
148
  if (req.headers['if-none-match'] === etag) {
@@ -172,8 +175,8 @@ function md2uiPlugin(siteConfig) {
172
175
  res.statusCode = 400; res.end('缺少文档路径'); return
173
176
  }
174
177
 
175
- const docDir = dirname(resolve(userDir, docPath))
176
- if (!docDir.startsWith(userDir)) {
178
+ const docDir = dirname(resolve(docsRoot, docPath))
179
+ if (!docDir.startsWith(docsRoot)) {
177
180
  res.statusCode = 403; res.end('禁止访问'); return
178
181
  }
179
182
 
@@ -187,7 +190,7 @@ function md2uiPlugin(siteConfig) {
187
190
 
188
191
  fs.writeFileSync(targetPath, body)
189
192
 
190
- // 返回相对于用户目录的路径(对路径各段做 URL 编码)
193
+ // 返回相对于文档根目录的路径(对路径各段做 URL 编码)
191
194
  const docDirRel = dirname(docPath)
192
195
  const encodedDir = docDirRel && docDirRel !== '.'
193
196
  ? docDirRel.split('/').map(encodeURIComponent).join('/')
@@ -206,7 +209,7 @@ function md2uiPlugin(siteConfig) {
206
209
  }
207
210
  // 文档内容
208
211
  if (req.url?.startsWith('/@user-docs/')) {
209
- const filePath = resolve(userDir, decodeURIComponent(req.url.replace('/@user-docs/', '')))
212
+ const filePath = resolve(docsRoot, decodeURIComponent(req.url.replace('/@user-docs/', '')))
210
213
  if (fs.existsSync(filePath)) {
211
214
  // 根据扩展名设置 Content-Type
212
215
  const extName = filePath.split('.').pop().toLowerCase()
@@ -254,10 +257,14 @@ function md2uiPlugin(siteConfig) {
254
257
  }
255
258
 
256
259
  async function start() {
260
+ // 解析参数,支持位置参数指定扫描目录
261
+ const cliArgs = parseArgs()
262
+ const scanDir = cliArgs.dir ? resolve(userDir, cliArgs.dir) : userDir
263
+
257
264
  console.log(`\n md2ui - Markdown 文档预览工具\n`)
258
- console.log(` 扫描目录: ${userDir}\n`)
265
+ console.log(` 扫描目录: ${scanDir}\n`)
259
266
 
260
- if (!hasMdFiles(userDir)) {
267
+ if (!hasMdFiles(scanDir)) {
261
268
  console.log(' 当前目录下没有找到 Markdown 文件 (.md)\n')
262
269
  console.log(' 请在包含 .md 文件的目录中运行此命令\n')
263
270
  process.exit(1)
@@ -265,15 +272,21 @@ async function start() {
265
272
 
266
273
  // 加载配置
267
274
  const userConfig = await loadUserConfig()
268
- const cliArgs = parseArgs()
269
275
  const siteConfig = { ...defaultConfig, ...userConfig, ...cliArgs }
276
+ delete siteConfig.dir
270
277
 
271
278
  const server = await createServer({
272
279
  root: pkgRoot,
273
- configFile: resolve(pkgRoot, 'vite.config.js'),
274
- plugins: [md2uiPlugin(siteConfig)],
280
+ configFile: false,
281
+ plugins: [
282
+ (await import('@vitejs/plugin-vue')).default(),
283
+ md2uiPlugin(siteConfig, scanDir)
284
+ ],
275
285
  server: {
276
286
  port: siteConfig.port
287
+ },
288
+ optimizeDeps: {
289
+ include: ['vue', 'marked', 'mermaid']
277
290
  }
278
291
  })
279
292
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "md2ui",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "type": "module",
5
5
  "description": "将本地 Markdown 文档转换为美观的 HTML 页面",
6
6
  "author": "",
@@ -54,7 +54,7 @@
54
54
  "katex": "^0.16.45",
55
55
  "lucide-vue-next": "^0.556.0",
56
56
  "marked": "^11.1.1",
57
- "mermaid": "^10.6.1",
57
+ "mermaid": "^11.14.0",
58
58
  "minisearch": "^7.2.0",
59
59
  "tiptap-markdown": "^0.9.0",
60
60
  "vite": "^5.0.0",
@@ -36,6 +36,8 @@
36
36
  > console.log('引用中的代码块')
37
37
  >
38
38
  >
39
+ >
40
+ >
39
41
  > ```
40
42
 
41
43
  ## 列表