update at 2025-10-09 12:39:24

This commit is contained in:
douboer
2025-10-09 12:39:24 +08:00
parent a891153be0
commit 6f51916b50
44 changed files with 332 additions and 226 deletions

151
docs/architecture.md Normal file
View File

@@ -0,0 +1,151 @@
# Architecture Overview
> 本文档从整体视角拆分自 `detaildesign.md`,聚焦架构分层、核心模块职责与交互关系。补充细粒度时序与图片处理细节请参见:
> - `image-pipeline.md`
> - `render-service-blueprint.md`
> - `diagrams.md`
## 1. 分层结构
```
UI / Interaction (NotePreview)
├─ Toolbar (复制/上传/发草稿/图片集/导出/批量)
└─ 状态维护 (当前笔记、主题、代码高亮、公众号 AppId)
Rendering & Composition (ArticleRender + MarkedParser + Extensions)
├─ Markdown 预处理 (frontmatter 剥离 / 可选图片语法转换)
├─ Gallery 展开 (短代码 & 块级 figure src|link → wikilink 列表)
├─ 语法扩展 (LocalFile: wikilink 图片、文件嵌入、Excalidraw、SVG)
├─ 行级轻语法 (applyCustomInlineBlocks: fig / ||r||g||b||y||)
├─ 延迟元素缓存 (Mermaid / Excalidraw)
└─ 样式注入 (主题 + 代码高亮 + 自定义 CSS)
Assets & Settings Layer
├─ AssetsManager (themes, highlights, customCSS)
└─ NMPSettings (frontmatter key 映射 / 功能开关 / 微信配置 / galleryPrePath & galleryNumPic & defaultCoverPic)
Resource & Media Layer
├─ LocalImageManager (图片登记 / 上传 / 替换 / base64 嵌入)
├─ Image Conversion (WebP -> JPG wasm)
└─ html-to-image (Mermaid/Excalidraw 转 PNG)
Cover Fallback Chain (逻辑横切 Concern)
frontmatter cover/image → 正文首本地图片 → gallery 生成列表首图 → defaultCoverPic (配置) → 空
Debug Logging & Throttle
- 输出:当前文件路径、封面决策(包含 defaultCoverPic 触发)
- 节流:同路径 3 秒内不重复打印
WeChat Integration Layer
├─ Token 代理 (wxGetToken)
├─ 草稿创建 (wxAddDraft / wxAddDraftImages)
├─ 素材批量获取 (wxBatchGetMaterial)
└─ 上传图片 (wxUploadImage)
Utilities & Helpers
├─ debounce, applyCSS, waitForLayoutReady
└─ CardDataManager (代码卡片序列化/恢复)
```
## 2. 核心模块职责矩阵
| 模块 | 关键职责 | 输入 | 输出 | 失败模式 |
|------|----------|------|------|----------|
| NotePreview | 交互、调度、批处理 | 用户操作 / 活动文件 | 渲染触发、发布调用 | 文件为空 / 未配置公众号 |
| ArticleRender | 渲染 + 元数据 + 发布协调 | Markdown + Settings | HTML + DraftArticle | 解析错误 / token 失败 |
| MarkedParser + Extensions | Markdown Token 化扩展 | 预处理文本 | Token 树 -> HTML 片段 | 不支持语法 / 路径缺失 |
| LocalFile | Wikilink/嵌入/Excalidraw/SVG | Token.raw | 标准 HTML / 占位 | 文件不存在 / AuthKey 缺失 |
| LocalImageManager | 图片生命周期 | 图片引用集合 | 上传后的 URL 替换结果 | 上传失败 / 转码失败 |
| AssetsManager | 主题 & 高亮加载 | 文件系统 | CSS 文本 | 主题缺失 |
| NMPSettings | 全局配置 | 存储数据 | 配置实例 | AuthKey 无效 |
| WeChat API | 外部接口封装 | 请求结构 | 响应 JSON | HTTP 非 200 / errcode |
| CardDataManager | 代码块序列化 | HTML fragment | 可复制安全内容 | 序列化不匹配 |
## 3. 关键交互流程简述
### 3.1 渲染触发
1. 用户打开/切换文件 → `file-open` 事件。
2. `NotePreview.update()` → 清理旧图片缓存 → `ArticleRender.renderMarkdown()`
3. 读取 Markdown → (frontmatter 剥离 + 可选图片语法转换) → Marked 解析扩展 → HTML section → 延迟元素二次渲染。
4. 更新 UI 下拉:主题 / 高亮 / 公众号。
### 3.2 上传图片
1. 用户点击“上传图片” → `ArticleRender.uploadImages()`
2. 获取 token → 缓存元素转图片 → 本地/远程图片逐步上传 → DOM src 替换 → 复制 HTML 到剪贴板。
### 3.3 发布草稿
1. “发草稿” → token → 缓存元素转图片。
2. 上传本地 & 远程图片 → 封面决策thumb_media_id/frontmatter/正文首图/默认素材)→ 构造 `DraftArticle`
3. 调用 `wxAddDraft` → 返回 media_id。
### 3.4 发布图片集 (newspic)
与草稿类似,但构造 `DraftImages`content 使用纯文本,图片列表为 `media_id` 数组。
## 4. 元数据 & 封面策略抽象
逻辑函数(伪):
```ts
function resolveCover(originalMarkdown: string, fmCover?: string, thumbMediaId?: string): string | null {
if (thumbMediaId) return null; // 已有 media_id 不再上传本地封面
if (fmCover) return fmCover; // frontmatter 指定
const body = stripFrontmatter(originalMarkdown);
const candidates = collectImageOrder(body); // wikilink + markdown
// 若正文无本地候选再尝试 gallery 展开结果
if (!candidates.length) {
const galleryList = collectGalleryFirstImages(body);
if (galleryList.length) candidates.push(galleryList[0]);
}
if (candidates.length) return `![[${candidates[0]}]]`;
// 最终 defaultCoverPic 由外层 getMetadata 注入(若配置)
return null;
}
```
Fallback 扩展:`getMetadata()` 在上述返回为空且存在 `defaultCoverPic` 时作为最终封面。
## 5. 图片收集策略统一要点
- Wikilink解析时即登记路径 → vault file
- Markdown 图片:可配置预处理转 Wikilink以复用同一逻辑避免重复正则后处理
- DOM 补偿策略(如后续新渲染管线未登记图片):可在上传前扫描 `<img>` 回填缺失项。
## 6. 错误处理分层
| 层 | 代表错误 | 处理策略 |
|----|----------|----------|
| 输入层 | 没有活动文件 | 静默返回 / UI 提示 |
| 渲染层 | Marked 解析异常 | try/catch 显示“渲染失败” HTML |
| 媒体层 | 图片上传失败 | Notice + 继续其他图片 |
| 转码层 | wasm 未加载 | 降级:保持 webp 原样尝试上传 |
| 发布层 | token 获取失败 | 抛异常终止流程 |
| API 层 | errcode != 0 | 聚合错误信息 + 建议手动复制 |
## 7. 性能关注点
| 项目 | 当前 | 潜在优化 |
|------|------|----------|
| 图片上传 | 串行 | 并发队列 + 重试退避 |
| Mermaid/Excalidraw | 前台转 PNG | 结果缓存 / worker 线程 |
| 主题加载 | 每次刷新全部组合 | 按需拼接 + 缓存 hash |
| Markdown 解析 | 单线程 | 增量渲染(监听 diff |
## 8. 可扩展挂载点 (未来)
| Hook | 说明 | 预期参数 |
|------|------|----------|
| beforeRender | Markdown 转 HTML 前 | { markdown, file } |
| afterRender | HTML 完成但未上传 | { html, metadata } |
| beforeUploadImages | 上传前 | { images[] } |
| afterUploadImages | 上传后 | { mapping } |
| beforePublish | 调用 wxAddDraft 前 | { draft } |
| afterPublish | 成功返回 | { media_id } |
## 9. 风险摘录
- 多管线并存(旧 ArticleRender vs 新 RenderService 占位)易导致图片未登记 → 需统一抽象。
- 自动封面选取对远程图片/非图片扩展尚无过滤完备策略。
- 正则预处理与 Marked tokenizer 逻辑耦合度高,重构时需单测保护。
- 默认封面文件不存在导致封面缺失但用户误以为已设置 → 需未来加入存在性校验与 Notice。
- link/caption 属性当前解析未输出 → 未来转型时注意兼容老内容。
## 10. 索引 / 交叉引用
| 文档 | 内容概述 |
|------|----------|
| detaildesign.md | 全量深度设计描述 |
| image-pipeline.md | 图片解析、上传、封面、正则清单 |
| render-service-blueprint.md | 新一代渲染服务设计计划 |
| diagrams.md | 架构 / 时序 / 类关系图 (Mermaid) |
---
> 若修改架构(新增层或跨层依赖),需同步更新本文件与 `diagrams.md`。