@fgbg/mdocs 0.8.9 → 0.8.12
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/agent-skills/changelog/SKILL.md +298 -0
- package/agent-skills/core-concepts-all-files/SKILL.md +53 -0
- package/agent-skills/core-concepts-domain/SKILL.md +106 -0
- package/agent-skills/core-concepts-invitation/SKILL.md +61 -0
- package/agent-skills/core-concepts-no-account/SKILL.md +84 -0
- package/agent-skills/deployment-config/SKILL.md +47 -0
- package/agent-skills/deployment-requirements/SKILL.md +50 -0
- package/agent-skills/deployment-reverse-proxy/SKILL.md +71 -0
- package/agent-skills/faq/SKILL.md +48 -0
- package/agent-skills/getting-started-first-kb/SKILL.md +40 -0
- package/agent-skills/getting-started-installation/SKILL.md +119 -0
- package/agent-skills/index/SKILL.md +52 -0
- package/agent-skills/index.json +191 -0
- package/agent-skills/usage-agent-dev-loop/SKILL.md +179 -0
- package/agent-skills/usage-bookmarks/SKILL.md +97 -0
- package/agent-skills/usage-cli-token/SKILL.md +132 -0
- package/agent-skills/usage-comments/SKILL.md +149 -0
- package/agent-skills/usage-domain-members/SKILL.md +102 -0
- package/agent-skills/usage-drafts/SKILL.md +123 -0
- package/agent-skills/usage-flowchart/SKILL.md +108 -0
- package/agent-skills/usage-markdown/SKILL.md +130 -0
- package/agent-skills/usage-merge-conflicts/SKILL.md +42 -0
- package/agent-skills/usage-my-documents/SKILL.md +108 -0
- package/agent-skills/usage-onboarding-ai/SKILL.md +65 -0
- package/agent-skills/usage-recovery-code/SKILL.md +87 -0
- package/agent-skills/usage-search/SKILL.md +34 -0
- package/agent-skills/usage-settings/SKILL.md +95 -0
- package/agent-skills/why-mdocs/SKILL.md +13 -0
- package/dist/server/agent/Agent/run.js +222 -0
- package/dist/server/agent/Agent/run.js.map +1 -0
- package/dist/server/agent/Agent/session-manager.js +147 -0
- package/dist/server/agent/Agent/session-manager.js.map +1 -0
- package/dist/server/agent/Agent/system-prompt.js +13 -0
- package/dist/server/agent/Agent/system-prompt.js.map +1 -0
- package/dist/server/agent/Agent/tools.js +37 -0
- package/dist/server/agent/Agent/tools.js.map +1 -0
- package/dist/server/agent/Config/config.js +113 -0
- package/dist/server/agent/Config/config.js.map +1 -0
- package/dist/server/agent/Skill/skill-loader.js +46 -0
- package/dist/server/agent/Skill/skill-loader.js.map +1 -0
- package/dist/server/app.js +2 -0
- package/dist/server/app.js.map +1 -1
- package/dist/server/db/repositories/agent-model-config.repo.js +17 -0
- package/dist/server/db/repositories/agent-model-config.repo.js.map +1 -0
- package/dist/server/db/schema.js +10 -0
- package/dist/server/db/schema.js.map +1 -1
- package/dist/server/routes/agent.routes.js +135 -0
- package/dist/server/routes/agent.routes.js.map +1 -0
- package/dist/web/assets/{MergeView-CTeS5Pgb.js → MergeView-Da6W6Mwd.js} +1 -1
- package/dist/web/assets/{_baseUniq-BEyyLo4a.js → _baseUniq-DIXaUG3P.js} +1 -1
- package/dist/web/assets/{arc-DRyJIB49.js → arc-BdrqKgEt.js} +1 -1
- package/dist/web/assets/{architectureDiagram-Q4EWVU46-C6FcFqys.js → architectureDiagram-Q4EWVU46-C7DbabmE.js} +1 -1
- package/dist/web/assets/{blockDiagram-DXYQGD6D-C5DamiPe.js → blockDiagram-DXYQGD6D-xpzHPtBf.js} +1 -1
- package/dist/web/assets/{c4Diagram-AHTNJAMY-BQf9874A.js → c4Diagram-AHTNJAMY-C55XB-0p.js} +1 -1
- package/dist/web/assets/channel-R2F1bwis.js +1 -0
- package/dist/web/assets/{chunk-4BX2VUAB-CvLXGWM9.js → chunk-4BX2VUAB-Cw9cGcvA.js} +1 -1
- package/dist/web/assets/{chunk-4TB4RGXK-C2B5cSFk.js → chunk-4TB4RGXK-Bb7TaNsp.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-C-va7Y5a.js → chunk-55IACEB6-ClfU0bTR.js} +1 -1
- package/dist/web/assets/{chunk-EDXVE4YY-NG3zjl2t.js → chunk-EDXVE4YY-DEYQg7so.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-A2P0ciLw.js → chunk-FMBD7UC4-l0uxylnu.js} +1 -1
- package/dist/web/assets/{chunk-OYMX7WX6-Cto0U3kG.js → chunk-OYMX7WX6-CTuAfYj2.js} +1 -1
- package/dist/web/assets/{chunk-QZHKN3VN-DNdWRP-4.js → chunk-QZHKN3VN-Cd5BdpCj.js} +1 -1
- package/dist/web/assets/{chunk-YZCP3GAM-B7BWetQd.js → chunk-YZCP3GAM-C4AFz6HK.js} +1 -1
- package/dist/web/assets/classDiagram-6PBFFD2Q-D8Aoi_kK.js +1 -0
- package/dist/web/assets/classDiagram-v2-HSJHXN6E-D8Aoi_kK.js +1 -0
- package/dist/web/assets/clone-D3UTWyOI.js +1 -0
- package/dist/web/assets/{cose-bilkent-S5V4N54A-DAp6XOTI.js → cose-bilkent-S5V4N54A-DPbGSIxQ.js} +1 -1
- package/dist/web/assets/{dagre-KV5264BT-bXw64vAF.js → dagre-KV5264BT-BAqCvioS.js} +1 -1
- package/dist/web/assets/{diagram-5BDNPKRD-BZyIxgPb.js → diagram-5BDNPKRD-BVhjoylL.js} +1 -1
- package/dist/web/assets/{diagram-G4DWMVQ6-B7DIbmE6.js → diagram-G4DWMVQ6-BgdBEUo2.js} +1 -1
- package/dist/web/assets/{diagram-MMDJMWI5-CYIS8pup.js → diagram-MMDJMWI5-v3XiVR4L.js} +1 -1
- package/dist/web/assets/{diagram-TYMM5635-iVE2rLmi.js → diagram-TYMM5635-Bnlc4JL7.js} +1 -1
- package/dist/web/assets/{erDiagram-SMLLAGMA-TYkyJdZq.js → erDiagram-SMLLAGMA-DZNfy5XO.js} +1 -1
- package/dist/web/assets/{flowDiagram-DWJPFMVM-DCq4RRIH.js → flowDiagram-DWJPFMVM-CyNHaoXD.js} +1 -1
- package/dist/web/assets/{ganttDiagram-T4ZO3ILL-BwOIx_Vs.js → ganttDiagram-T4ZO3ILL-D9XKVK6L.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-UUTBAWPF-CS9cfxUA.js → gitGraphDiagram-UUTBAWPF-BsoJR5By.js} +1 -1
- package/dist/web/assets/{graph-K8x8ab-D.js → graph-C6hZEMMA.js} +1 -1
- package/dist/web/assets/{index-DRsX6c0H.js → index-BiYwrQhS.js} +1220 -1186
- package/dist/web/assets/index-C4tGH1XB.css +1 -0
- package/dist/web/assets/{infoDiagram-42DDH7IO-DFs9J8cW.js → infoDiagram-42DDH7IO-EsbSvvwg.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-UXIWVN3A-ChYUj0ld.js → ishikawaDiagram-UXIWVN3A-opc9PUAq.js} +1 -1
- package/dist/web/assets/{journeyDiagram-VCZTEJTY-CysvVjkr.js → journeyDiagram-VCZTEJTY-CGoqXdQp.js} +1 -1
- package/dist/web/assets/{kanban-definition-6JOO6SKY-DlGvCOou.js → kanban-definition-6JOO6SKY-BsMSOTEO.js} +1 -1
- package/dist/web/assets/{layout-DDk1jHzS.js → layout-dka4PN3u.js} +1 -1
- package/dist/web/assets/{linear-CCo9IeHT.js → linear-C7358dWt.js} +1 -1
- package/dist/web/assets/{min-BTxfBtS6.js → min-CkhEOvqb.js} +1 -1
- package/dist/web/assets/{mindmap-definition-QFDTVHPH-D2Y8ZrN3.js → mindmap-definition-QFDTVHPH-Cw5Uw5sO.js} +1 -1
- package/dist/web/assets/{pieDiagram-DEJITSTG-DuaVu740.js → pieDiagram-DEJITSTG-D_2NhEs9.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-34T5L4WZ-D9P6tcbK.js → quadrantDiagram-34T5L4WZ-CCoI5QqP.js} +1 -1
- package/dist/web/assets/{requirementDiagram-MS252O5E-B8v3RtvO.js → requirementDiagram-MS252O5E-DlRuHrpI.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-XADWPNL6-CJIIvTEv.js → sankeyDiagram-XADWPNL6-CqeHUQiU.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-FGHM5R23-WgQSy-Eh.js → sequenceDiagram-FGHM5R23-bAgSxA1M.js} +1 -1
- package/dist/web/assets/{stateDiagram-FHFEXIEX-Bg9XaNxo.js → stateDiagram-FHFEXIEX-BY710eMg.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-QKLJ7IA2-BQw6J9EK.js +1 -0
- package/dist/web/assets/{timeline-definition-GMOUNBTQ-2h7ZeLc6.js → timeline-definition-GMOUNBTQ-Dm1cJJzA.js} +1 -1
- package/dist/web/assets/{vennDiagram-DHZGUBPP-Ab3_6Oe9.js → vennDiagram-DHZGUBPP-x15pVuxW.js} +1 -1
- package/dist/web/assets/{wardley-RL74JXVD-DVPCK5Ky.js → wardley-RL74JXVD-Baa2vTyp.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-NUSXRM2D-rM9jo8v5.js → wardleyDiagram-NUSXRM2D-DD4pCNVv.js} +1 -1
- package/dist/web/assets/{xychartDiagram-5P7HB3ND-BnxoasRp.js → xychartDiagram-5P7HB3ND-Cj82t7kB.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +7 -1
- package/dist/web/assets/channel-CiCXcXC3.js +0 -1
- package/dist/web/assets/classDiagram-6PBFFD2Q-DLatDrXa.js +0 -1
- package/dist/web/assets/classDiagram-v2-HSJHXN6E-DLatDrXa.js +0 -1
- package/dist/web/assets/clone-CSlMEjIx.js +0 -1
- package/dist/web/assets/index-BUN3YDVd.css +0 -1
- package/dist/web/assets/stateDiagram-v2-QKLJ7IA2-BZf_Cq1t.js +0 -1
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: changelog
|
|
3
|
+
name: "更新日志"
|
|
4
|
+
description: "- **文档移动**:侧栏可拖拽 Markdown 文档到文件夹 / 同目录文章旁 / 域根;仅创建者后端成功;`POST /api/documents/:id/move` - **上手助手入口**:悬浮按钮可按住拖动定位,位置写入本地;支持重置;面板随入口侧移 - **空文档白屏**:AI/空 markdown 创建的 Lexical `children: []` 会在打开时补空段落,避免编辑器"
|
|
5
|
+
keywords: []
|
|
6
|
+
source: changelog.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 更新日志
|
|
10
|
+
|
|
11
|
+
## v0.8.12
|
|
12
|
+
|
|
13
|
+
- **文档移动**:侧栏可拖拽 Markdown 文档到文件夹 / 同目录文章旁 / 域根;仅创建者后端成功;`POST /api/documents/:id/move`
|
|
14
|
+
- **上手助手入口**:悬浮按钮可按住拖动定位,位置写入本地;支持重置;面板随入口侧移
|
|
15
|
+
- **空文档白屏**:AI/空 markdown 创建的 Lexical `children: []` 会在打开时补空段落,避免编辑器整页崩溃
|
|
16
|
+
- **Agent**:建文/建文件夹/移动后刷新侧栏树;新增 `move_document` 工具
|
|
17
|
+
|
|
18
|
+
## v0.8.11
|
|
19
|
+
|
|
20
|
+
- **上手助手会话**:浮层支持「+」新建会话、历史列表切换并回放;标题取自首条用户消息
|
|
21
|
+
- **手册**:[上手助手(AI)](./usage/onboarding-ai.md) 同步会话管理说明
|
|
22
|
+
|
|
23
|
+
## v0.8.10
|
|
24
|
+
|
|
25
|
+
- **上手助手(AI)**:左下角浮动入口;设置页「AI」配置个人 DeepSeek Key;按访客落盘会话(`tenant/<id>/agent/session`),多轮续聊;回答引用手册页面链接;思考中三点动画;跟随滚动仅在贴底时生效
|
|
26
|
+
- **手册**:新增 [上手助手(AI)](./usage/onboarding-ai.md)
|
|
27
|
+
|
|
28
|
+
## v0.8.9
|
|
29
|
+
|
|
30
|
+
- **编辑器依赖**:升级 `@fgbg/lobe-editor@1.0.0-fork.16`——导出 `INSERT_MARKMAP_COMMAND`,斜杠 Markmap 使用正式 command API
|
|
31
|
+
- **编辑器顶栏**:撤销/重做后新增「文档顶部插入空行」「文档末尾插入空行」
|
|
32
|
+
- **斜杠菜单**:增加 Meta2d、Markmap 快捷插入
|
|
33
|
+
- **发布后视口**:服务端正文与刚发布内容一致时不再整棵 `setDocument` 重挂,减轻 Mermaid 等块导致的跳动
|
|
34
|
+
|
|
35
|
+
## v0.8.8
|
|
36
|
+
|
|
37
|
+
- **编辑器依赖**:升级 `@fgbg/lobe-editor@1.0.0-fork.15`——仅当反引号之间有内容时才转为行内代码,避免空 `` 抢占导致无法输入 fenced 代码块;并补充 Meta2d 斜杠插入后自动打开编辑器
|
|
38
|
+
|
|
39
|
+
## v0.8.7
|
|
40
|
+
|
|
41
|
+
- **发布后视口跳动**:发布成功后仍会拉取最新 meta / head 并清除本地草稿,但当服务端正文与刚发布内容一致时,不再对编辑器执行整棵 `setDocument` 重挂,避免 Mermaid 等块因 DOM 重建导致视觉窗口跳动
|
|
42
|
+
- **编辑器依赖**:升级 `@fgbg/lobe-editor@1.0.0-fork.14`(Mermaid 渲染结果缓存与加载占位,减轻重挂场景下的高度塌陷)
|
|
43
|
+
|
|
44
|
+
## v0.8.5
|
|
45
|
+
|
|
46
|
+
- **目录描述版本链**:新建文件夹时自动创建的 `___desc___.md` 现在与普通文档一样写入首版 commit 和 `headCommitId`;升级后启动时会为历史上缺少 head 的目录描述从磁盘补迁移,修复「无法发布:缺少版本基准」
|
|
47
|
+
- **自动发布失败打标**:任意自动发布失败(缺版本基准、404、API 错误等)都会在 IndexedDB 草稿上写入 `publishError`,自动扫描会跳过重试;可在设置页「未发布草稿」查看失败原因并手动重试或另存
|
|
48
|
+
- **合并页懒加载**:MergeView 改为按需加载,减小首屏主包体积
|
|
49
|
+
|
|
50
|
+
## v0.8.4
|
|
51
|
+
|
|
52
|
+
- **前端体积**:升级 `@fgbg/lobe-editor@fork.13`,Shiki 语法高亮仅保留约 40 种常用语言(见下方列表),`dist/web` 资源文件减少;冷门语言代码块以纯文本显示,内容不丢失
|
|
53
|
+
|
|
54
|
+
## v0.8.3
|
|
55
|
+
|
|
56
|
+
- **静态资源压缩**:Express 启用 gzip(`compression`),JS/CSS 等响应带 `Content-Encoding: gzip`,首屏传输量显著下降
|
|
57
|
+
- **静态资源缓存**:`/assets/*`(带 hash 的文件)设置 `Cache-Control: public, max-age=31536000, immutable`,二次打开更快
|
|
58
|
+
|
|
59
|
+
## v0.8.2
|
|
60
|
+
|
|
61
|
+
- **全局安装 Web UI**:修复 `npm install -g` 后访问 `/` 显示 `Cannot GET /`——前端静态目录改为相对安装包路径解析,不再依赖启动时的当前工作目录
|
|
62
|
+
|
|
63
|
+
## v0.8.1
|
|
64
|
+
|
|
65
|
+
- **服务监听地址**:默认 `MDOCS_HOST` 从 `127.0.0.1` 改为 `0.0.0.0`,服务器部署后外网可直接访问(本地仅本机可设 `MDOCS_HOST=127.0.0.1`)
|
|
66
|
+
|
|
67
|
+
## v0.8.0
|
|
68
|
+
|
|
69
|
+
- **CLI 全局安装**:修复 `bin/mdocs.js` 无执行权限导致 `npm install -g` 后 `mdocs: Permission denied` 的问题
|
|
70
|
+
|
|
71
|
+
## v0.7.9
|
|
72
|
+
|
|
73
|
+
- **前端文档状态重构(activeDocMeta)**:
|
|
74
|
+
- 当前打开文档的服务端元信息(权限、路径、head、标题等)与正文分离:正文由编辑器 + IndexedDB 草稿承载,不再写入混合的 `activeDoc` 对象
|
|
75
|
+
- 打开文档:有草稿则只加载草稿正文,否则加载服务器正文;meta 始终来自 GET
|
|
76
|
+
- 发布成功(手动 / 自动):删除本地草稿 → 再 GET → 刷新 meta 与编辑器,修复单用户自动发布后误报版本冲突
|
|
77
|
+
- 按文档串行队列处理自动保存与自动发布,降低 publish 与 save 交错导致的 commit 滞后
|
|
78
|
+
- 有未发布草稿时不做 sync「落后」轮询,减少与本地副本冲突的提示噪声
|
|
79
|
+
- 发布后编辑器仅原地更新内容,避免整页 remount 闪烁
|
|
80
|
+
- **合并(Merge)体验**:
|
|
81
|
+
- 409 / diverged 时提供三栏合并界面(本地 / 结果 / 远端),行内处理差异块
|
|
82
|
+
- 服务端 `GET .../merge-context` 提供合并祖先(LCA)正文,用于三路对比
|
|
83
|
+
- 合并发布成功后同样删草稿并拉取最新文档
|
|
84
|
+
|
|
85
|
+
## v0.7.8
|
|
86
|
+
|
|
87
|
+
- **草稿副本模型收敛**:
|
|
88
|
+
- 草稿以 `documentId` 为主键,保存正文与开编基准 commit(`baseCommitId`),并在首次编辑落盘时携带文档快照信息,后续自动保存只更新内容相关字段
|
|
89
|
+
- 发布冲突(409)统一进入冲突处理流程,避免普通错误提示与 merge 提示重复弹窗
|
|
90
|
+
- **同步 / 拉取行为简化**:
|
|
91
|
+
- 有未发布草稿时,不再执行覆盖式 pull,避免本地副本被意外覆盖
|
|
92
|
+
- 无未发布草稿时,点击「拉取更新」会直接拉取远端最新内容并刷新编辑区
|
|
93
|
+
- 修复“拉取后数据已更新但编辑器 UI 未同步”的问题
|
|
94
|
+
- **权限一致性修复**:
|
|
95
|
+
- 前端编辑权限判断回到服务端最新文档元信息,避免草稿旧 meta 造成“看起来可编辑但发布被拒绝”的误判
|
|
96
|
+
- 后端修复 public 域下 `public_read` 文档 + `invite(edit)` 的编辑判定(被邀请编辑者现在可正常发布)
|
|
97
|
+
- **错误提示机制统一**:
|
|
98
|
+
- API 错误由网络层统一分发,App 全局统一弹窗处理
|
|
99
|
+
- 右下角提示保留为 success/info 反馈,并统一为灰框样式
|
|
100
|
+
|
|
101
|
+
## v0.7.7
|
|
102
|
+
|
|
103
|
+
- **评论功能体验优化**:
|
|
104
|
+
- 评论内容保留换行显示:在 `.mdocs-comment-content` 增加 `white-space: pre-wrap`,发出的评论保留输入时的换行和空格,不再被折叠成一坨
|
|
105
|
+
- 评论面板宽度可拖动:左边缘新增蓝色拖拽条,支持 280px ~ 600px 自由调整
|
|
106
|
+
- 评论输入框高度可拖动:输入框顶部新增灰色拖拽条,按住向上拖让输入框变高(60px ~ 600px),适合写长评论
|
|
107
|
+
- 实现说明:放弃浏览器原生 `resize: vertical`(只能从右下角往下拖),改用 React state + 自定义顶部 handle,textarea 高度由 state 接管
|
|
108
|
+
- 详见 `fgbg-docs/comments-panel-resize.md`
|
|
109
|
+
- **评论输入区布局优化**:
|
|
110
|
+
- 字符计数改为浮动显示在输入框右下角,不再独占一行,节省 ~30-40px 垂直空间,评论列表可显示更多内容
|
|
111
|
+
- 输入区域上下 padding 从 16px 精简为 12px,拖拽手柄尺寸缩小为 32×3px,整体更紧凑
|
|
112
|
+
- 详见 `fgbg-docs/comments-layout-optimization.md`
|
|
113
|
+
- **评论输入框高度自动适配**:
|
|
114
|
+
- 输入换行自动撑高输入框,删空自动缩回默认高度(80px),无需手动拖拽
|
|
115
|
+
- 高度上限 300px,超出后显示滚动条
|
|
116
|
+
- 与手动拖拽逻辑不冲突,拖拽后内容变化仍可自动适配
|
|
117
|
+
|
|
118
|
+
## v0.7.6
|
|
119
|
+
|
|
120
|
+
- **Demo 模式完善**:补全缺失的 Mock API,消除 501 错误
|
|
121
|
+
- 新增书签 Mock API:收藏/取消收藏/收藏列表
|
|
122
|
+
- 新增评论 Mock API:发表/查看/删除评论
|
|
123
|
+
- 新增文档邀请 Mock API:邀请访客/移除邀请/查看邀请
|
|
124
|
+
- 新增我的文档 Mock API:按所有者过滤文档
|
|
125
|
+
- 新增访客目录 Mock API:返回访客列表
|
|
126
|
+
- **Demo 模式 UI 优化**:
|
|
127
|
+
- 隐藏无意义的退出登录按钮
|
|
128
|
+
- 设置页新增黄色提示条,说明 Demo 模式限制
|
|
129
|
+
- 优化 Demo Banner 文案:"部分功能被禁用,请勿长期存储重要数据"
|
|
130
|
+
- **编辑器收藏状态可视化**:在域下拉框右侧新增收藏状态按钮
|
|
131
|
+
- 实心黄色星标 + "已收藏" 文字直观显示当前文档收藏状态
|
|
132
|
+
- 空心灰色星标表示未收藏,点击一键切换
|
|
133
|
+
- 与文档信息菜单的收藏状态双向同步
|
|
134
|
+
- **Bug 修复**:
|
|
135
|
+
- 修复设置页「我的收藏」列表显示域 ID 而非域名称的问题,现在加载域列表并通过 ID → 名称映射正确显示
|
|
136
|
+
- 修复切换设置页后返回文档丢失编辑内容的问题:`DocumentEditor` 挂载时主动检查 IndexedDB 草稿,若内容与服务器版本不同则自动恢复草稿内容和标题
|
|
137
|
+
- 修复 `useAutoSave` Hook 中 `useCallback` 依赖循环导致监听器反复注册的性能问题
|
|
138
|
+
- **Vite 依赖预构建优化**:增加 `optimizeDeps` 配置,优化首次冷启动速度
|
|
139
|
+
|
|
140
|
+
## v0.7.5
|
|
141
|
+
|
|
142
|
+
- **修复 Markdown 粘贴列表时 listItem 被错误拆分**:升级 `@fgbg/lobe-editor` 至 `1.0.0-fork.12`
|
|
143
|
+
- **根因**:`listItem` markdown reader 通过 `children.map()` 返回数组,解析器的 `.flat()` 将数组展平导致单个 list item 被拆成多个独立节点
|
|
144
|
+
- **症状**:粘贴 `1. **开关关闭时**:不查询果切任务` 时,有序列表被拆成两个 listItem(value=1 和 value=2)
|
|
145
|
+
- **修复**:reader 改为返回单个节点,嵌套列表和 paragraph children 正确合入同一个 listItem
|
|
146
|
+
- 详见 `fgbg-docs/references/listitem-parsing-bugfix.md`
|
|
147
|
+
|
|
148
|
+
## v0.7.4
|
|
149
|
+
|
|
150
|
+
- **从上游根本解决编辑器内容溢出问题**:升级 `@fgbg/lobe-editor` 至 `1.0.0-fork.9`
|
|
151
|
+
- **表格宽度溢出修复**:在 `.editor_table_scrollable_wrapper` 增加 `min-width: 0`,解决 flex 布局下宽表格撑开父容器的经典问题
|
|
152
|
+
- **图片宽度溢出修复**:在 `.image` / `.blockImage` 样式中增加 `img { max-width: 100% !important; }`,防止大图片横向撑开编辑器
|
|
153
|
+
- **修复 Outline 大纲被挤出视野**:给 Editor + Outline 共享的外层 Block 增加 `minWidth: 0`,确保左侧目录树展开时,大纲不会被宽表格挤出视野
|
|
154
|
+
- **保留 mdocs 侧补丁作为双重保险**:待上游稳定后可移除
|
|
155
|
+
- **升级 `@fgbg/lobe-editor` 至 `1.0.0-fork.10`**(仍属 v0.7.4 产品线,仅上游编辑器迭代;mdocs 应用包版本号未改):
|
|
156
|
+
- **Markmap**:`---markmap---` 正确注册 `IMarkdownShortCutService`;嵌套 `textarea` 粘贴不再走主编辑器 Markdown 粘贴链路;预览区按钮可右下角;**新增一键展开/折叠全部节点**,节点数超过 30 个时默认全部折叠;**修复左侧 markdown 编辑器无法全选问题**(`Cmd/Ctrl+A` 事件被 Lexical 全局拦截,需 `stopPropagation`)
|
|
157
|
+
- **链接**:左键重复打开链接编辑浮层;⌘/Ctrl+单击或中键新标签打开;修复异步场景 `getLatest` 报错(改为 `read` + `$getNodeByKey`);`EDIT_LINK_COMMAND` 移至 `LinkNode.ts`
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
## v0.7.3
|
|
161
|
+
|
|
162
|
+
- **新增 Markmap 思维导图支持**:在 ` ```markmap ` 代码块中输入 Markdown 即可渲染为可交互思维导图
|
|
163
|
+
- 实时预览:编辑 Markdown 时下方实时渲染思维导图
|
|
164
|
+
- 全屏预览:点击图表进入全屏模式,支持缩放、拖拽
|
|
165
|
+
- 错误处理:语法错误时显示友好的红色错误提示
|
|
166
|
+
- 交互一致:与 Mermaid 流程图的交互行为完全相同
|
|
167
|
+
- 升级 `@fgbg/lobe-editor` 至 `1.0.0-fork.7`
|
|
168
|
+
- **修复编辑器图片宽度溢出问题**:增加 `.mdocs-editor-content-area img { max-width: 100% !important; }` 样式规则,覆盖 Antd Image 组件的内联样式,防止大图片横向撑开编辑器容器
|
|
169
|
+
|
|
170
|
+
## v0.7.2
|
|
171
|
+
|
|
172
|
+
- **修复登录接口被 auth 中间件拦截的问题**:新增 `/visitors/login` 到豁免路径白名单,解决登录时提示 `missing visitor token` 的错误
|
|
173
|
+
|
|
174
|
+
## v0.7.0
|
|
175
|
+
|
|
176
|
+
- **新增登录密码功能**:解决跨浏览器/跨设备登录痛点,访客可设置密码,在任何设备使用「用户名+密码」登录
|
|
177
|
+
- 注册弹窗改为 Tab 结构:左侧注册、右侧登录,无需跳转页面
|
|
178
|
+
- 注册两步流:输入名称 → 可选设置密码
|
|
179
|
+
- 登录支持两种方式:用户名密码 / 恢复码
|
|
180
|
+
- 设置页新增「登录密码」管理卡片,可随时修改密码
|
|
181
|
+
- **多设备同时在线**:新增 `visitor_sessions` 会话表,支持多个设备同时登录同一账号,互不干扰
|
|
182
|
+
- **向后兼容**:未设置密码的访客仍可在原设备正常使用;所有已存在账号默认密码为 `1234`,登录后可自行修改
|
|
183
|
+
|
|
184
|
+
## v0.6.9
|
|
185
|
+
|
|
186
|
+
- **升级 @lobehub/editor 至 1.0.0-fork.6**,同步上游修复:
|
|
187
|
+
- **修复 Meta2d 弹窗按钮暗色模式不可见**:DiagramEditor 弹窗硬编码 `background: '#fff'` 但未重置文字颜色,暗色主题下所有按钮(撤销/重做/删除/适应/100%/关闭)白底白字。加 `color: '#000'` 修复
|
|
188
|
+
- **Meta2d 流程图 SVG 预览导出稳定**:SVG 导出优先用当前编辑实例而非隐藏实例重放,修复多 pen 场景部分导出为空
|
|
189
|
+
- **修复划词 ColorPicker 选色后跳回黑色**:selection 为 null 时保留上次检测到的颜色值
|
|
190
|
+
- **Locale 深合并 + BlockImage 插入光标流**:
|
|
191
|
+
- `registerLocale()` 改为深合并,避免插件注册 `{codemirror:{...}}` 时覆盖已有 `meta2d.editor` 等嵌套 key
|
|
192
|
+
- BlockImageNode 通过 `---meta2d---` 或粘贴插入后,自动创建空白段落并定位光标,不再卡在图片后无法继续输入
|
|
193
|
+
|
|
194
|
+
## v0.6.8
|
|
195
|
+
|
|
196
|
+
- **修复划词 ColorPicker 选色后跳回黑色**:修复选中文本后通过浮动工具栏的 ColorPicker 设置颜色时,颜色面板立即跳回黑色的问题。根因为 `useEditorState` 在 selection 为 null(如 ColorPicker popup 导致编辑器失焦)时错误清空了 `textColor`/`bgColor`,现改为保留上一次检测到的颜色值,避免无选区时误判格式状态
|
|
197
|
+
- **升级 @lobehub/editor 至 1.0.0-fork.4**,同步上游修复:
|
|
198
|
+
- **修复编辑器销毁泄漏**:`ReactEditor` 和 `useEditor` 增加 `destroy()` cleanup,配合 `pendingDestroyRef` + `queueMicrotask` 兼容 StrictMode remount
|
|
199
|
+
- **Markdown 粘贴智能检测**:移除评分机制改为始终转换,代码块内粘贴防光标跳转,Mermaid 错误友好提示,空链接 Enter 自动转换
|
|
200
|
+
- **Meta2d 流程图预览修复**:SVG 预览与下载尺寸对齐,过滤 `isShowChild=false` 的 pens,高大预览图自动居中并支持滚动
|
|
201
|
+
- **工具栏状态即时更新**:移除 500ms debounce,加粗/斜体/颜色等状态立即响应
|
|
202
|
+
- **大纲工具栏切换**:新增 `useOutlineActionItem`,工具栏可一键展开/折叠大纲面板
|
|
203
|
+
|
|
204
|
+
## v0.6.7
|
|
205
|
+
|
|
206
|
+
- **草稿发布失败恢复机制**:自动发布遇到服务端文档不存在(404)时,草稿不再静默丢失或无限循环报错,而是标记为发布失败状态并通知用户;用户可在草稿列表页点击「另存为新文档」,通过域选择器 + 目录树选择目标位置,将草稿内容作为全新文档重新发布
|
|
207
|
+
- **修复 Lexical 编辑器内存泄漏**:修复切换文档时内存飙升至 40GB 的致命问题。根因为 `@lobehub/editor` 的 `ReactEditor` 组件创建编辑器实例后从不调用 `destroy()`,且 `DocumentEditor` 使用 `key` 强制重新挂载导致每次切换都泄漏一个完整的编辑器实例(含 CodeMirror、Meta2d Canvas、图片等 DecoratorNode 资源)。上游 `ReactEditor` 和 `useEditor()` hook 已增加 `destroy()` cleanup,mdocs 侧移除多余的 `key` 并增加防御性清理
|
|
208
|
+
- **兼容 React StrictMode 的编辑器生命周期**:修复 StrictMode 开发环境下 `editor.destroy()` 后重新挂载导致 `DataSource for type "json" is not registered` 报错。采用 `pendingDestroyRef` + `queueMicrotask` 延迟取消模式:cleanup 中把 destroy 排队到 microtask,若紧接着是 StrictMode remount 则同步取消,真正卸载时才执行销毁
|
|
209
|
+
- **批量修复异步组件卸载泄漏**:为 `CommentsPanel`、`SettingsPage`、`DraftListPage`、`RecoveryDialog`、`DocumentEditor` 的异步请求增加卸载保护。`CommentsPanel` 采用 `expectedDocumentIdRef` 竞态保护丢弃旧请求;其余组件采用 `mountedRef` 模式防止卸载后 `setState`
|
|
210
|
+
- **浏览器资源泄漏清理**:修复 Playground 中 `URL.createObjectURL` 未 `revokeObjectURL` 的问题;修复 `actions.ts` 文件选择器在 Safari 中取消后 DOM 节点未移除的问题(增加 5s 兜底超时);修复 Playground 卸载后 `window.editor` 和 debounce 定时器未清理的问题
|
|
211
|
+
|
|
212
|
+
## v0.6.6
|
|
213
|
+
|
|
214
|
+
- **设置页面大改版**:重新组织设置导航,新增「我的收藏」和「我的文章」两个独立 Tab
|
|
215
|
+
- **我的收藏表格视图**:收藏列表改为表格布局,支持标题搜索,显示域名、作者、收藏时间四列
|
|
216
|
+
- **我的文章列表**:集中展示当前访客创建的所有文档,按更新时间倒序排列;支持标题/域名搜索;每篇可直接打开或邀请成员
|
|
217
|
+
- **文档邀请快捷入口**:我的文章列表每行新增「邀请成员」按钮,无需打开文档即可配置访问权限
|
|
218
|
+
|
|
219
|
+
## v0.6.5
|
|
220
|
+
|
|
221
|
+
- **自动保存性能优化**:修复 `useAutoSave` Hook 中 `useCallback` 依赖循环问题,使用 `useRef` 保存频繁变化的值,避免 Lexical 监听器反复注册注销,减少不必要的性能开销
|
|
222
|
+
- **切换文档竞态修复**:修复快速连续切换文档时,旧请求后返回导致编辑器内容与 URL 中 `documentId` 不匹配的问题,新增 `expectedDocIdRef` 竞态检查机制
|
|
223
|
+
- **评论列表性能优化**:`CommentsPanel` 评论列表渲染从 O(n*m) 优化为 O(n),使用 `useMemo` + Map 单次遍历完成根评论与回复分组,同时顺便计算未删除评论总数
|
|
224
|
+
- **编辑器初始化优化**:移除 `DocumentEditor.handleInit` 中重复的 `JSON.parse` 逻辑,直接复用已预计算的 `contentType`
|
|
225
|
+
- **代码清理**:删除已标记 `@deprecated` 的 `deleteFolderApiV0` 函数(已被递归删除目录的 `deleteFolderApi` 替代)
|
|
226
|
+
|
|
227
|
+
## v0.6.4
|
|
228
|
+
|
|
229
|
+
- **文档邀请成员**:编辑器工具栏文档信息菜单新增「邀请成员」入口,可邀请访客以只读或编辑权限协作文档
|
|
230
|
+
- **邀请权限选择**:邀请弹窗中右侧已选成员列表新增 MiniSelect 下拉框,可为每个被邀请人独立设置「只读」/「可编辑」权限
|
|
231
|
+
- **MiniSelect 组件**:新增紧凑型通用下拉组件,支持点击外部关闭、Escape 键、键盘可访问
|
|
232
|
+
- **邀请编辑 Bug 修复**:修复了被邀请用户虽然能通过后端鉴权但前端编辑器仍以只读模式渲染的问题 — 后端 `getDocument()` 现在返回 `invitedEdit` 标记,前端 `canEdit` 计算补充 invite 检查
|
|
233
|
+
- **后端权限修正**:`canEditDocument()` 在 private 域各权限档位下补充 `document_invites` 检查,被 invite edit 的非创建者现在可正常编辑
|
|
234
|
+
- **10 条新增单测**:覆盖 invite read/edit 跨所有权限档位(private/domain_read/domain_write/public_read/public_write)
|
|
235
|
+
|
|
236
|
+
## v0.6.3
|
|
237
|
+
|
|
238
|
+
- **文档信息菜单**:编辑器工具栏新增三条线菜单按钮,可查看文档元信息(创建者、创建时间、大小、上次编辑),支持快速收藏/取消收藏
|
|
239
|
+
- **文档权限修改入口**:文档信息菜单中预留权限修改入口(后续版本开放完整功能
|
|
240
|
+
- **收藏功能**:侧边栏新增「我的收藏」入口,支持一键收藏/取消收藏文档,已删除文档的收藏保留显示便于手动取消
|
|
241
|
+
- **Lucide SVG 图标**:收藏、退出登录按钮统一使用 Lucide SVG 图标替代 emoji,hover 时有缩放和颜色变化的视觉反馈
|
|
242
|
+
- **收藏弹窗大改版**:「我的收藏」弹窗重构为表格布局(`<table>`),标题/域/作者/收藏时间四列对齐;新增名称搜索框和域筛选下拉;每行新增📖快速打开按钮;操作按钮支持即时 tooltip;标题超长时自动截断并显示原生 tooltip;取消收藏有淡出动画
|
|
243
|
+
- **作者与收藏时间显示**:后端 LEFT JOIN visitors 表获取文档作者名,前端每行展示作者 + `Intl.RelativeTimeFormat` 相对时间(自动适配中英文)
|
|
244
|
+
- **Cookie 有效期延长**:身份 Cookie 从 1 年延长到 10 年,实现"永久"登录体验
|
|
245
|
+
- **登录态稳定性优化**:修复因请求头占位符覆盖有效 Cookie 导致刷新后需要重新登录的问题
|
|
246
|
+
|
|
247
|
+
## v0.6.2
|
|
248
|
+
|
|
249
|
+
- **访客名称全局唯一**:`visitor_name` 增加数据库 `UNIQUE` 约束,避免同名混淆
|
|
250
|
+
- **migrate 支持按名称迁移**:`pnpm mdocs visitor migrate --from Alice --to Bob`,不再需要输入 UUID
|
|
251
|
+
- **个人域路径处理移到后端**:前端不再需要 visitorId 判断路径,Tree API 自动根据当前访客身份返回美化后的路径
|
|
252
|
+
- **登录态 BUG 修复**:修复了因请求头占位符覆盖有效 Cookie 导致刷新后需要重新登录的问题
|
|
253
|
+
|
|
254
|
+
## v0.6.0
|
|
255
|
+
|
|
256
|
+
- **访客恢复码**:新增访客身份恢复机制,生成一次性恢复码,丢失浏览器本地 token 后可凭码恢复访客身份及所有文档权限
|
|
257
|
+
|
|
258
|
+
## v0.5.0
|
|
259
|
+
|
|
260
|
+
- **全文搜索**:新增 FTS5 搜索引擎,支持中文分词(jieba),在搜索框输入关键词即可按 BM25 相关性排序检索全库文档
|
|
261
|
+
- **后端 Markdown 转 Lexical**:编辑器和 API 支持直接传入 Markdown 文本,后端自动转换为 Lexical JSON 存储。CLI 客户端 `create` / `update` 默认使用 `contentFormat: 'markdown'`
|
|
262
|
+
- **域切换持久化**:刷新页面后域选择不丢失,自动恢复到上次浏览的域
|
|
263
|
+
- **mdocs-cli 命令行客户端**:新增独立 CLI 工具仓库 `https://github.com/xuhuafeifei/mdocs-cli`,提供 `search`、`get`、`create`、`update`、`domains`、`mkdir` 六个命令,Token 在设置页创建
|
|
264
|
+
|
|
265
|
+
## v0.4.0
|
|
266
|
+
|
|
267
|
+
- **CLI Token**:新增命令行身份令牌,可在设置页创建/重置,支持 `x-cli-token` 认证头,继承访客所有权限
|
|
268
|
+
- **ConfirmDialog 组件**:通用确认弹窗,替代原生 `window.confirm`
|
|
269
|
+
|
|
270
|
+
## v0.3.0
|
|
271
|
+
|
|
272
|
+
- **显式目录模型**:引入 `file_type`(`'dir'` / `'md'`)和 `parent_id`,目录不再是路径切割的产物
|
|
273
|
+
- **空目录支持**:可以创建没有子文档的空目录
|
|
274
|
+
- **磁盘路径域隔离**:每个域拥有独立的磁盘子目录(`~/.mdocs/files/docs/{domain_id}/`),不同域同名文件不再冲突
|
|
275
|
+
- **目录描述文件改名**:从 `desc.md` 改为 `___desc___.md`,避免与用户创建的文件冲突
|
|
276
|
+
- **新建目录接口**:新增 `POST /api/folders`,创建目录时自动创建 `___desc___.md`
|
|
277
|
+
- **树构建优化**:按 `parent_id` 一次查询建树,不再递归切割路径
|
|
278
|
+
|
|
279
|
+
## v0.2.0
|
|
280
|
+
|
|
281
|
+
- **权限模型重构**:从四级权限升级为五级权限(`private` → `domain_read` → `domain_write` → `public_read` → `public_write`),invite 从档位改为独立叠加层
|
|
282
|
+
- **域约束生效**:public / restricted 域类型现在限制域内文档可选档位(public 仅 3/4,restricted 仅 1/2)
|
|
283
|
+
- **邀请互斥**:域成员不能再被 invite,减少权限混淆
|
|
284
|
+
- **鉴权收拢**:所有权限判断集中在统一模块,不再分散在各服务和中间件
|
|
285
|
+
- 受限域(restricted domain)支持
|
|
286
|
+
|
|
287
|
+
## v0.1.0
|
|
288
|
+
|
|
289
|
+
- 项目初始化
|
|
290
|
+
- 基于 Lexical 的富文本编辑器,支持标题、表格、代码块、数学公式
|
|
291
|
+
- Meta2d 流程图拖拽编辑器
|
|
292
|
+
- SQLite + 文件系统存储
|
|
293
|
+
- 无账户访客身份识别(UUID token + SHA-256)
|
|
294
|
+
- 域隔离(公共域 + 个人域)
|
|
295
|
+
- 文档级邀请协作(只读 / 编辑)
|
|
296
|
+
- IndexedDB 本地草稿自动保存
|
|
297
|
+
- 中英文双语界面
|
|
298
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: core-concepts-all-files
|
|
3
|
+
name: "所见皆文件"
|
|
4
|
+
description: "mdocs 的存储模型将文档目录树映射为两层结构:"
|
|
5
|
+
keywords: []
|
|
6
|
+
source: core-concepts/all-files.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 所见皆文件
|
|
10
|
+
|
|
11
|
+
mdocs 的存储模型将文档目录树映射为两层结构:
|
|
12
|
+
|
|
13
|
+
- **SQLite** 维护逻辑关系(父子、权限、元数据)
|
|
14
|
+
- **文件系统** 存储实际内容(Markdown / Lexical JSON)
|
|
15
|
+
|
|
16
|
+
## 逻辑结构
|
|
17
|
+
|
|
18
|
+
`documents` 表中的每行记录代表一个节点:
|
|
19
|
+
|
|
20
|
+
| `file_type` | 含义 | `relative_path` | `parent_id` |
|
|
21
|
+
|-------------|------|-----------------|-------------|
|
|
22
|
+
| `dir` | 目录 | 域内相对路径(如 `folder/sub`) | 指向父目录的 `document_id` |
|
|
23
|
+
| `md` | 文档 | 完整路径(如 `folder/sub/a.md`) | 指向父目录的 `document_id` |
|
|
24
|
+
|
|
25
|
+
目录树由 `parent_id` 关系直接确定,不依赖路径切割。
|
|
26
|
+
|
|
27
|
+
## 物理存储
|
|
28
|
+
|
|
29
|
+
文档内容以 Lexical JSON 格式写入磁盘:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
~/.mdocs/files/docs/{domain_id}/folder/sub/a.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- `{domain_id}` 是域的唯一标识,每个域拥有独立的磁盘子目录
|
|
36
|
+
- 磁盘路径与 `relative_path` 一一对应
|
|
37
|
+
- 目录节点(`file_type = 'dir'`)不写磁盘文件,仅存在于数据库中
|
|
38
|
+
|
|
39
|
+
## 目录描述
|
|
40
|
+
|
|
41
|
+
每个目录可以附带一个 `___desc___.md` 文件:
|
|
42
|
+
|
|
43
|
+
- 路径为 `{dirPath}/___desc___.md`
|
|
44
|
+
- `parent_id` 指向该目录的 `document_id`
|
|
45
|
+
- 前端用其内容作为目录描述展示
|
|
46
|
+
- **v0.8.5+**:与普通 `.md` 文档相同,拥有 `headCommitId` 与发布版本链;编辑目录描述后可正常发布
|
|
47
|
+
|
|
48
|
+
## 设计意图
|
|
49
|
+
|
|
50
|
+
- SQLite 管理逻辑结构(谁是父目录、谁有权限)
|
|
51
|
+
- 文件系统管理实际数据(Markdown / JSON 内容)
|
|
52
|
+
- 域之间在磁盘上完全隔离,不同域可以拥有同名文件
|
|
53
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: core-concepts-domain
|
|
3
|
+
name: "域隔离(Domain)"
|
|
4
|
+
description: "mdocs 中的「域」是最顶层的逻辑隔离单元。它的设计目标是:"
|
|
5
|
+
keywords: []
|
|
6
|
+
source: core-concepts/domain.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 域隔离(Domain)
|
|
10
|
+
|
|
11
|
+
## 设计意图
|
|
12
|
+
|
|
13
|
+
mdocs 中的「域」是最顶层的逻辑隔离单元。它的设计目标是:
|
|
14
|
+
|
|
15
|
+
- 不同团队或项目之间的文档在**浏览入口**(域列表、侧栏树)上彼此隔离
|
|
16
|
+
- 在不引入复杂 RBAC 的前提下实现最基本的访问边界
|
|
17
|
+
- 让每个用户拥有一个「个人域」作为私密工作区
|
|
18
|
+
|
|
19
|
+
域是存在于数据库逻辑上的虚拟概念,文档通过 `domain_id` 字段归属到某个域。
|
|
20
|
+
|
|
21
|
+
## 三种域类型
|
|
22
|
+
|
|
23
|
+
| 域类型 | 谁可以进入 | 文档 permission 档位 | 用途 |
|
|
24
|
+
|--------|-----------|---------------------|------|
|
|
25
|
+
| **public**(公开域)| 任何人(含未登录访客) | 仅 `public_read(3)`、`public_write(4)` | 开放协作,默认域 |
|
|
26
|
+
| **restricted**(受限域)| **域成员** 与 **创建者** 为完整入口;仅被某篇文档 invite 的访客为受限入口(可见相关文档,**不能**凭此在域内任意新建文档) | 仅 `domain_read(1)`、`domain_write(2)` | 团队内部知识库 |
|
|
27
|
+
| **private**(个人域)| 仅域主(`domain_id === visitor_id`) | 0~4 **全部**档位均可 | 私人笔记本 |
|
|
28
|
+
|
|
29
|
+
> 域类型会**约束**域内文档可选的 permission 值——public 域不允许 private 档,restricted 域不允许 public 档。这是与之前版本的关键区别。
|
|
30
|
+
|
|
31
|
+
## 五级文档权限
|
|
32
|
+
|
|
33
|
+
每篇文档有一个 `permission` 字段(0~4),定义谁能读、谁能写(在「能接触到该文档」的前提下):
|
|
34
|
+
|
|
35
|
+
| 数值 | 名称 | 谁可读 | 谁可写 |
|
|
36
|
+
|------|------|--------|--------|
|
|
37
|
+
| 0 | private | 仅 owner | 仅 owner |
|
|
38
|
+
| 1 | domain_read | 域成员 | 仅 owner |
|
|
39
|
+
| 2 | domain_write | 域成员 | 域成员 |
|
|
40
|
+
| 3 | public_read | 任何人 | 仅 owner |
|
|
41
|
+
| 4 | public_write | 任何人 | 任何人 |
|
|
42
|
+
|
|
43
|
+
<!--  -->
|
|
44
|
+
|
|
45
|
+
### 档位与域类型的约束关系
|
|
46
|
+
|
|
47
|
+
| 域类型 | 允许的文档 permission | 说明 |
|
|
48
|
+
|--------|----------------------|------|
|
|
49
|
+
| **public** | **仅** `public_read(3)`、`public_write(4)` | 公开域内不允许出现「仅域成员」或「仅 owner」的文档 |
|
|
50
|
+
| **restricted** | **仅** `domain_read(1)`、`domain_write(2)` | 受限域内文档不暴露给域外任何人;非成员若需访问则靠 **invite** 叠加 |
|
|
51
|
+
| **private** | **全部** 0~4 | 不设档位上限;private 域下文档也可以设为 `public_write(4)` 对外公开 |
|
|
52
|
+
|
|
53
|
+
### 创建默认值
|
|
54
|
+
|
|
55
|
+
| 域类型 | 新建文档默认 permission |
|
|
56
|
+
|--------|----------------------|
|
|
57
|
+
| private | `private(0)` |
|
|
58
|
+
| restricted | `domain_read(1)` |
|
|
59
|
+
| public | `public_read(3)` |
|
|
60
|
+
|
|
61
|
+
## invite:独立叠加层
|
|
62
|
+
|
|
63
|
+
在五级权限之上,还有一个独立于档位的 **invite** 机制:owner 可以为任意一篇文档添加受邀者(read / edit),不受文档当前档位限制。
|
|
64
|
+
|
|
65
|
+
- invite **不是**一个权限档位(它不是 0~4 中的一员)
|
|
66
|
+
- invite 与域成员**互斥**:已经是域成员的人,不能再被 invite
|
|
67
|
+
- 鉴权顺序:owner → 档位语义 → invite 兜底
|
|
68
|
+
|
|
69
|
+
详见 [文档级邀请](./invitation.md)。
|
|
70
|
+
|
|
71
|
+
## 鉴权流程(概要)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
读权限:
|
|
75
|
+
1. owner → 放行
|
|
76
|
+
2. public 域 → 3/4 档放行
|
|
77
|
+
3. restricted 域 → 域成员走 1/2 档;非成员走 invite
|
|
78
|
+
4. private 域 → 按档位实际语义 + invite
|
|
79
|
+
|
|
80
|
+
写权限:
|
|
81
|
+
1. owner → 放行
|
|
82
|
+
2. public 域 → 仅 4 档放行
|
|
83
|
+
3. restricted 域 → 仅 2 档且为域成员;非成员走 invite
|
|
84
|
+
4. private 域 → 按档位实际语义
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 个人域(Private)
|
|
88
|
+
|
|
89
|
+
- 每个访客注册时自动创建一个个人域,`domain_id` 等于该访客的 `visitor_id`
|
|
90
|
+
- 个人域**只有域主一个成员**(不通过 `domain_members` 表维护多成员)
|
|
91
|
+
- 文件权限可设为 0~4 任意档位——即使名为「个人」域,也可以公开某篇文档
|
|
92
|
+
- 创建文档时默认权限为 `private(0)`
|
|
93
|
+
|
|
94
|
+
## 列表 vs 直链
|
|
95
|
+
|
|
96
|
+
侧栏树、域下列表会按域准入过滤;若某人持有**文档 ID 直链**,读权限主要由**文档档位 + invite** 决定——例如 restricted 域内一篇 `domain_read` 文档,对非域成员不可读(除非被 invite)。需要更强保密时,请用 **`private(0)`** 档。
|
|
97
|
+
|
|
98
|
+
## 设计取舍
|
|
99
|
+
|
|
100
|
+
- **不引入团队/组织树**:域只是逻辑标签。对于小团队,一个 public 域 + 每人一个 private 域就足够
|
|
101
|
+
- **域隔离在数据库和文件系统两个层面**:磁盘上每个域拥有独立的子目录(`~/.mdocs/files/docs/{domain_id}/`),数据库通过 `domain_id` 进行查询过滤;跨域「移动」需更新数据库记录并移动磁盘文件
|
|
102
|
+
|
|
103
|
+
**操作说明**(创建受限域、维护成员、套用模板):见 [受限域成员与名单模板](../usage/domain-members.md)。
|
|
104
|
+
|
|
105
|
+
行为以 mdocs 应用代码与 SQLite schema 为准;随版本迭代本页会跟进。
|
|
106
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: core-concepts-invitation
|
|
3
|
+
name: "文档级邀请"
|
|
4
|
+
description: "传统文档协作需要先注册账户、加入团队、然后才能编辑——门槛太高。mdocs 的邀请机制只针对「文档」这个最小粒度,且被邀请者不需要预先注册。"
|
|
5
|
+
keywords: []
|
|
6
|
+
source: core-concepts/invitation.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 文档级邀请
|
|
10
|
+
|
|
11
|
+
## 设计意图
|
|
12
|
+
|
|
13
|
+
传统文档协作需要先注册账户、加入团队、然后才能编辑——门槛太高。mdocs 的邀请机制只针对「文档」这个最小粒度,且被邀请者不需要预先注册。
|
|
14
|
+
|
|
15
|
+
## 工作流程
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
文档所有者 → 添加受邀者(填写对方的访客 ID)→ 选择权限 → 受邀者刷新后即可访问
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
邀请记录存储在数据库中,关联了文档 ID、访客 ID 和权限等级。
|
|
22
|
+
|
|
23
|
+
## 权限等级
|
|
24
|
+
|
|
25
|
+
| 权限 | 说明 |
|
|
26
|
+
|------|------|
|
|
27
|
+
| 只读(read) | 可查看文档内容,不可编辑 |
|
|
28
|
+
| 编辑(edit) | 可编辑文档内容 |
|
|
29
|
+
|
|
30
|
+
## 设计要点
|
|
31
|
+
|
|
32
|
+
1. **基于访客 ID,而非邮箱**:mdocs 没有用户账户系统,所以邀请的载体是访客 ID——每个浏览器注册后获得的唯一标识
|
|
33
|
+
2. **文档级粒度**:不是整个域或整个项目,而是单篇文档。适合「这篇文档需要给某人看一下」的场景
|
|
34
|
+
3. **与档位解耦**:邀请不是权限档位——它独立于文档的五级权限(0~4)之上。任何档位的文档都可以叠加 invite,不受限制
|
|
35
|
+
4. **所有者和受邀者的关系在数据库中存储**:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
document_invites 表
|
|
39
|
+
├── document_id → 文档 ID
|
|
40
|
+
├── visitor_id → 被邀请的访客 ID
|
|
41
|
+
└── permission → "read" 或 "edit"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
邀请仅由文档所有者管理。所有者可以随时撤销邀请。
|
|
45
|
+
|
|
46
|
+
## 与域成员互斥
|
|
47
|
+
|
|
48
|
+
一条重要约束:**已是某域成员的人,不能再被该域内文档邀请**。域成员已经拥有域内文档的读/写权限(取决于档位),invite 是给**域外人员**的通道。
|
|
49
|
+
|
|
50
|
+
- **restricted 域**:域成员直接走 `domain_read(1)` / `domain_write(2)` 档位语义,不需要也不应该被 invite
|
|
51
|
+
- **private 域**:域内仅有域主一人,实际效果相同——无法 invite 域主
|
|
52
|
+
- **public 域**:public 域没有域成员概念,invite 不会因此被拦截
|
|
53
|
+
|
|
54
|
+
## invite 在各域类型中的角色
|
|
55
|
+
|
|
56
|
+
| 域类型 | invite 的作用 |
|
|
57
|
+
|--------|-------------|
|
|
58
|
+
| **public** | 对非 owner 补充写权限(`public_read(3)` 档文档默认仅 owner 可写);`public_write(4)` 档下用不到 invite |
|
|
59
|
+
| **restricted** | 非域成员通过 invite 获得**某篇文档**的读/写能力,同时在服务端呈现「经文档邀请」的域入口(不足以在域内任意新建文档;在域内随意创建内容需成为 `domain_members` 成员) |
|
|
60
|
+
| **private** | 非 owner 能否访问取决于文件档位 + invite 叠加。例如 `private(0)` 档文档,非 owner 只能通过 invite 进入 |
|
|
61
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: core-concepts-no-account
|
|
3
|
+
name: "无账户身份识别"
|
|
4
|
+
description: "早期不做传统用户系统(邮箱注册 / 账号密码那一套),每个访问者通过浏览器获得身份令牌即可开写。目标是零上手成本——打开就能用。"
|
|
5
|
+
keywords: []
|
|
6
|
+
source: core-concepts/no-account.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 无账户身份识别
|
|
10
|
+
|
|
11
|
+
## 设计意图
|
|
12
|
+
|
|
13
|
+
早期不做传统用户系统(邮箱注册 / 账号密码那一套),每个访问者通过浏览器获得身份令牌即可开写。目标是零上手成本——打开就能用。
|
|
14
|
+
|
|
15
|
+
后来为解决「换设备 / 清 Cookie 认不出人」,在**仍是访客模型**的前提下,增加了可选的登录密码;恢复码则是更早的自助找回手段,现已边缘化。详见 [恢复码与身份找回](../usage/recovery-code.md)。
|
|
16
|
+
|
|
17
|
+
## 身份模型
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
访客注册(输入昵称,可选设密码)
|
|
21
|
+
│
|
|
22
|
+
├─ 服务器生成 UUID(visitor_id)
|
|
23
|
+
├─ 生成高熵令牌(visitor_token,32 字节随机数 → base64url)
|
|
24
|
+
├─ 服务器只存储 SHA-256(令牌)(以及可选的密码哈希)
|
|
25
|
+
└─ 通过 HttpOnly Cookie 将原始令牌下发给浏览器
|
|
26
|
+
|
|
27
|
+
后续请求
|
|
28
|
+
└─ 浏览器自动携带 Cookie
|
|
29
|
+
└─ 服务器从 Cookie 读取令牌,验证 SHA-256 匹配 → 识别访客
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
前端**不存储任何认证令牌**,日常鉴权凭据由 HttpOnly Cookie 管理,XSS 无法直接读到令牌。
|
|
33
|
+
|
|
34
|
+
### Cookie 有效期
|
|
35
|
+
|
|
36
|
+
身份 Cookie 默认有效期为 **10 年**,实践中等同于「长期保持登录」。只要不主动清除浏览器站点数据,同一浏览器上会一直认得你。
|
|
37
|
+
|
|
38
|
+
> 💡 即使服务端重启或重新部署,已有 Cookie 在未过期前依然有效。
|
|
39
|
+
|
|
40
|
+
## 为什么这样做
|
|
41
|
+
|
|
42
|
+
- **低门槛**:不必先走邮箱验证;起个昵称就能写
|
|
43
|
+
- **令牌不落前端脚本可读存储**:日常身份靠 HttpOnly Cookie
|
|
44
|
+
- **跨端续身份(后来补上)**:设密码后可用「用户名 + 密码」在其他设备登录;未设密码则基本绑在当前浏览器
|
|
45
|
+
|
|
46
|
+
## 跨设备 / Cookie 丢失时
|
|
47
|
+
|
|
48
|
+
推荐顺序:
|
|
49
|
+
|
|
50
|
+
1. **用户名 + 密码登录**(设置页可管理登录密码)
|
|
51
|
+
2. **恢复码**(早期方案,登录弹窗次要入口;见 [恢复码](../usage/recovery-code.md))
|
|
52
|
+
3. 管理员 **访客迁移**(运维兜底)
|
|
53
|
+
|
|
54
|
+
### 访客迁移(管理员)
|
|
55
|
+
|
|
56
|
+
若用户既无密码又无可用恢复码,部署方可在服务器上将旧身份合并到新身份:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
# 推荐:按访客名称迁移(更简单,名称可在侧边栏看到)
|
|
60
|
+
pnpm mdocs visitor migrate --from Alice --to Bob --confirm
|
|
61
|
+
|
|
62
|
+
# 也支持按 UUID 迁移(精确匹配)
|
|
63
|
+
pnpm mdocs visitor migrate --from OLD_ID --to NEW_ID --confirm
|
|
64
|
+
|
|
65
|
+
# 试运行,查看影响范围但不实际执行
|
|
66
|
+
pnpm mdocs visitor migrate --from Alice --to Bob --dry-run
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
该操作在事务内执行,更新文档所有权,禁用旧访客,并记录审计日志。
|
|
70
|
+
|
|
71
|
+
### 查看所有访客
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
pnpm mdocs visitor list # 默认只看启用的访客
|
|
75
|
+
pnpm mdocs visitor list --all # 看全部(含已禁用的)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 设计取舍
|
|
79
|
+
|
|
80
|
+
- **放弃重型「用户体系」**换低准入;跨端能力用「可选密码」补齐,而不是一上来就上完整账号平台
|
|
81
|
+
- **HttpOnly Cookie 日常鉴权**:服务端重启不轻易丢当前浏览器会话
|
|
82
|
+
- **可以匿名浏览**:不注册也能看到公开域的公开文档
|
|
83
|
+
- **恢复码**:服务早期 Cookie-only 身份的自助找回;密码普及后降为兼容能力
|
|
84
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: deployment-config
|
|
3
|
+
name: "配置"
|
|
4
|
+
description: "mdocs **没有配置文件**。所有配置通过环境变量设置,遵循 12-Factor App 原则。"
|
|
5
|
+
keywords: []
|
|
6
|
+
source: deployment/config.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 配置
|
|
10
|
+
|
|
11
|
+
mdocs **没有配置文件**。所有配置通过环境变量设置,遵循 12-Factor App 原则。
|
|
12
|
+
|
|
13
|
+
## 完整配置项
|
|
14
|
+
|
|
15
|
+
| 环境变量 | 默认值 | 说明 |
|
|
16
|
+
|---------|--------|------|
|
|
17
|
+
| `MDOCS_HOST` | `0.0.0.0` | 监听地址(本机仅开发可设为 `127.0.0.1`) |
|
|
18
|
+
| `MDOCS_PORT` | `4000` | 监听端口 |
|
|
19
|
+
| `MDOCS_WEB_DIST` | (包内 `dist/web`) | 前端静态资源目录;全局 `npm install -g` 时一般无需设置 |
|
|
20
|
+
| `MDOCS_DATA_DIR` | `~/.mdocs` | 数据存储根目录 |
|
|
21
|
+
| `MDOCS_LOG_LEVEL` | `info` | 日志级别(trace/debug/info/warn/error/fatal/silent) |
|
|
22
|
+
| `MDOCS_CONSOLE_LEVEL` | `info` | 控制台日志级别 |
|
|
23
|
+
| `MDOCS_CONSOLE_STYLE` | `pretty` | 控制台日志格式(pretty/common/json) |
|
|
24
|
+
| `MDOCS_LOG_RETENTION_DAYS` | `14` | 日志保留天数 |
|
|
25
|
+
| `MDOCS_LOG_MAX_BYTES` | `5242880` | 单个日志文件最大字节数 |
|
|
26
|
+
|
|
27
|
+
## 使用示例
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 修改端口和数据目录
|
|
31
|
+
export MDOCS_PORT=3000
|
|
32
|
+
export MDOCS_DATA_DIR=/var/data/mdocs
|
|
33
|
+
|
|
34
|
+
pnpm start
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
或者一行启动:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
MDOCS_PORT=3000 MDOCS_DATA_DIR=/var/data/mdocs pnpm start
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 设计思路
|
|
44
|
+
|
|
45
|
+
- **环境变量 > 配置文件**:适合容器化部署(Docker/K8s),也适合托管平台(Railway、Fly.io 等)
|
|
46
|
+
- **无 YAML/TOML/JSON 配置**:减少一层复杂度和配置校验逻辑
|
|
47
|
+
|