docs: 新增编辑器即时渲染方案、实施与 P3 加固记录

- editor-live-rendering.md(新):Typora 式单编辑面方案——路线选型、装饰层分层设计、
  widget 规格、安全与风险、测试方案、P0–P3 实施拆解;§12 为实施与加固记录:
  两个实测缺陷的根因与修复、3000 行性能实测数据、§12.6 真机输入法人工门槛(阻塞发布)、
  §12.7 编辑区高度
- design.md §8.2:编辑器段落由「分屏实时预览」改为即时渲染表述,链接本方案并标注发布门槛
- decisions.md:D37–D52(装饰器路线、单一 ViewPlugin、行级 reveal、长文档补解析、
  选区端点行采集、reveal 二分、@codemirror/commands 仅为 devDependency、人工门槛、编辑区高度)
- acceptance.md:新增 M5 里程碑与 M5-G 人工门槛行,补 v1.1/v1.2 浏览器复走记录与用例数

文档先行,代码实现见后续提交。
This commit is contained in:
2026-09-11 01:02:36 +08:00
parent b1ea89ba3d
commit 9b0aff6f9f
4 changed files with 649 additions and 6 deletions
+9 -3
View File
@@ -104,7 +104,7 @@
| 路由 | react-router | 8.3.1 | library mode 成熟,博客+后台两个区足够 | TanStack Router 1.x(类型安全更强,但本项目路由简单) |
| 数据请求 | TanStack Query | 5.102.8 | 十几 kB 换来统一 loading/缓存/重试,值得 | 裸 fetch + 自写 hook |
| Markdown 渲染 | react-markdown + remark-gfm + rehype-sanitize + **rehype-highlight** | 10.1.0 / 4.0.1 / 6.0.0 / 7.0.2 | 组合标准;高亮选 rehype-highlight(**纯 class 输出、零内联样式**)而非 shiki(inline style),与严格 CSP 兼容 | shiki 4.4.3(准确度最高但产 inline style)、prism-react-renderer(近停更,不推荐) |
| Markdown 编辑器 | **CodeMirror 6**(@uiw/react-codemirror + @codemirror/lang-markdown) | 4.25.11 / 6.5.2 | 源码编辑 + 分屏实时预览,零魔法、可预期;图片粘贴自写 handler(≤50 行) | Tiptap 3.31(体验派,WYSIWYG+成熟图片上传,文档全);MDXEditor(重);ByteMD(字节已弃坑)、Vditor 4(体积大、心智旧) |
| Markdown 编辑器 | **CodeMirror 6**(@uiw/react-codemirror + @codemirror/lang-markdown) | 4.25.11 / 6.5.2 | 即时渲染(Typora 式:隐藏语法标记 + 光标处展开源码,见 [editor-live-rendering.md](editor-live-rendering.md)),零魔法、可预期;图片粘贴自写 handler(≤50 行) | Tiptap 3.31(体验派,WYSIWYG+成熟图片上传,文档全);MDXEditor(重);ByteMD(字节已弃坑)、Vditor 4(体积大、心智旧) |
| 状态管理 | React Query + Context(**不引入** zustand) | — | 会话态 + 服务端缓存已覆盖;确需跨页 UI 态再加 zustand(≈1kB) | redux(不必要) |
| 图标 | lucide-react | 1.42.0 | 活跃、风格统一(antd 组件内亦复用) | — |
@@ -401,7 +401,7 @@ SecurityHeaders(含 HSTS,§9.2)
| `/admin/login` | 登录页 | 口令登录、防爆破提示 |
| `/admin` | 管理列表 | 全部笔记(公/私标签可见)、状态开关、新建、删除(入回收站) |
| `/admin/trash` | 回收站 | 已删列表、恢复、一键清空 |
| `/admin/notes/new` `/admin/notes/:id/edit` | 编辑器 | CodeMirror 源码编辑 + 实时预览(分屏/切换)、元信息侧栏(标题/slug/标签选择器/发布日期/摘要/公开开关/置顶)、图片粘贴上传 |
| `/admin/notes/new` `/admin/notes/:id/edit` | 编辑器 | CodeMirror 即时渲染(Typora 式,见 [editor-live-rendering.md](editor-live-rendering.md))、元信息侧栏(标题/slug/标签选择器/发布日期/摘要/公开开关/置顶)、图片粘贴上传 |
| `*` | 404 | 统一兜底 |
### 8.2 核心技术要点
@@ -422,7 +422,13 @@ Markdown 原文
**编辑器(编辑态)**
- CodeMirror 6 + `@codemirror/lang-markdown`,`minimalSetup` + 行号 + 等宽字体;工具栏提供加粗/斜体/链接/代码/表格等 Markdown 辅助插入;
> 即时渲染(Typora 式)改造方案见 **[docs/editor-live-rendering.md](editor-live-rendering.md)**(v1.2,P0–P3 已实施并完成实机验证与性能实测);本段原「分屏实时预览」表述已被该方案取代,数据层与浏览态渲染管线不变。
> **发布门槛**:该方案 §12.6 的真机输入法回归(系统拼音 / 搜狗)是**阻塞发布的人工验收项**,当前未执行。
- CodeMirror 6 + `@codemirror/lang-markdown`,**即时渲染**:语法标记默认隐藏、光标所在行展开为源码(`web/src/editor/` 装饰层);
行号与活动行高亮仅在**源码模式**下显示,「源码模式」按钮即逃生舱(方案 §4.7);
正文排版与公开页共用 `--md-*` 契约变量(`index.css`),编辑态视觉 = 阅读态视觉;
工具栏提供加粗/斜体/链接/代码/表格等 Markdown 辅助插入;
- **图片粘贴/拖拽**:自写 paste/drop handler(≤50 行)→ `POST /api/admin/images` → 光标处插入 `![描述](/api/images/{id})`;
- **slug 策略**:首次保存时由标题自动生成——中文标题退化为 `post-<YYYYMMDD>`,与现有记录(含回收站)冲突时追加 `-2`/`-3` 直至唯一;**首次保存即定稿,此后除非用户手动修改否则永不变化**;用户手改与他人冲突 → 服务端 409 + 字段级错误提示,前端就地高亮;
- 自动保存:防抖 2s;大改动前本地兜底(失败时保留编辑态不丢内容)。