Files
note2any/docs/architecture.md
2025-10-09 12:39:24 +08:00

7.5 KiB
Raw Permalink Blame History

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)

与草稿类似,但构造 DraftImagescontent 使用纯文本,图片列表为 media_id 数组。

4. 元数据 & 封面策略抽象

逻辑函数(伪):

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