makecindy / makecindy/cindy

[Feature] 移动端 Markdown 文件阅读器渲染 Mermaid 流程图

Open
#4,419 0 comments 0 reactions 0 assignees View on GitHub
feature
Dominant language
TypeScript
Stars
2.7k
Forks
401
Avg merge
21h 48m
Merged PRs (30d)
776

Description

## 使用场景 / Use case

用户在手机客户端(远程查看被控电脑文件)打开一个包含 ```mermaid 围栏的 Markdown(.md)文档时,希望像读正文一样直接看到流程图/时序图,而不是一段 Mermaid 源码。

## 当前问题 / Current limitation

移动端 Markdown **文件阅读器**(渲染态)不渲染 Mermaid,围栏直接以代码块形态输出:

- `apps/mobile/src/session/selectableMarkdownHtml.ts:444-449`:`mermaid` 分支只输出 `

`(源码,另附 `data-mermaid-repaired-source`),没有任何 runtime 把它升级成图。

- `apps/mobile/src/session/MarkdownFileReader.tsx:8` 的模块注释明确写着「mermaid 以代码块形态显示(渲染成图留二期)」。
- 消费路径:`apps/mobile/app/files/preview/[sessionId].tsx:1152` → `MarkdownFileReader`(testID `filePreview.markdownRendered`)。

同一移动端其它面其实已经能渲染 Mermaid,所以这是内部口径不一致,不是端上缺能力:

- 聊天消息:`apps/mobile/src/session/MessageRenderer.tsx:5132-5152` 用 `ViewabilityGatedMermaidDiagram` 渲染图形(`message.mermaidDiagram`),点开 `message.mermaidPreviewButton` 进沉浸式全屏查看器(`:6537`);runtime 在 `apps/mobile/src/session/mermaidWebViewHtml.ts`。
- 对话分享图:`apps/mobile/src/session/conversationShareWebViewHtml.ts:95` 含 mermaid 块时注入 `window.mermaid.render`。
- Desktop:`apps/desktop/src/renderer/components/markdown/markdownMermaidLivePreview.ts` 把 ```mermaid 围栏渲染成 SVG,`FileBodyView.tsx` 还能点开源码编辑。

而且**同一个文件阅读 HTML 里,块级/行内公式已经会渲染**:`buildSelectableMarkdownHtml` 在文档含公式时按 `hasMath` 注入 KaTeX runtime(`buildMathRuntimeScript` → `buildKatexLoaderJs`,本地内联资源 + 超时,失败回退源码)。也就是说「本地 runtime 内联 + 失败降级源码」这条路径在本 WebView 里已有现成实现,Mermaid 只是没接上。

## 期望方案 / Proposed solution

在 `buildSelectableMarkdownHtml` 里沿用公式那条既有口径把 Mermaid 接上,不新起 WebView、不改依赖:

1. `mermaid` 分支保留现有源码占位(保证失败可读),继续写 `data-mermaid-source` / `data-mermaid-repaired-source`。
2. 仅当文档确实含 mermaid 块时才注入 Mermaid runtime(与 `hasMath` 同口径),runtime 取已随包分发的 `MOBILE_MERMAID_JS`(`apps/mobile/src/session/richContentAssets.generated.ts`,由 `apps/mobile/scripts/sync-rich-content-assets.mjs` 生成),超时或执行失败时保持源码展示,降级口径与 `mermaidWebViewHtml.ts` / `mathWebViewHtml.ts` 一致。
3. 渲染前复用现有 `@cindy/maker-shared/mermaid-autofix` 的 `repairMermaidSource`(本文件已 import)。
4. 图形配色走语义 token,由 `MarkdownFileReader` 现有的 `colors` 注入,Light / Dark 都要可读。

已知代价,请在实现时一并权衡:`node_modules/mermaid/dist/mermaid.min.js` 约 3.4MB,内联进文件阅读 WebView 会给含图形的文档增加一次性内存与解析开销;因此「无 mermaid 块不注入」是必须项,而不是可选优化。

## 验收标准

- 手机端打开含 ```mermaid 的 .md 文件,渲染态直接显示图形;长图/宽图不撑爆布局,正文滚动与行定位(`targetLine` 高亮)不回退。
- 渲染失败或语法错误时保持源码块可读,不出现空白页或半截 DOM。
- 无 mermaid 块的文档不加载 Mermaid runtime(与 `hasMath` 同口径)。
- Light / Dark 双模式图形均可读。
- 不改动 `apps/mobile/package.json` 依赖与原生配置(不触发冷更 / runtime fingerprint 变化);如确有必要,请在 PR 中显式标注并走冷更把关。
- 补充「mermaid 块进入最终渲染」的测试,口径对齐 `apps/mobile/src/__tests__/selectableMarkdownHtml.test.ts`。
- 文本选择与「添加到对话」引用(`MarkdownFileReader` 的 `xdtQuote` 菜单项)在图形混排下仍可用(图形本身不可选中即可)。

## 已考虑的替代方案 / Alternatives considered

- 维持代码块显示(现状):手机上看流程图必须脑补源码,与 Desktop、聊天消息的体验割裂。
- 另起 Mermaid WebView 渲染:会撞上消息流 `registerMobileMessageWebView` 那套并发配额,且文件阅读器是整页滚动,额外 WebView 的测高与同步成本高。
- 只做「点击源码全屏看图」:与 Desktop 编辑态内联预览不一致,手机端还多一次跳转。

## 环境 / Environment

- 源码分析基于 `origin/main` `88f712116`。
- 触发场景:手机客户端远程查看被控电脑上的 .md 文件(Markdown 渲染态)。
- 设备型号 / 客户端版本 / iOS 或 Android 版本:提交者未提供。

## 备注

如果「渲染成图留二期」是内部已排期的二期项,麻烦补一下排期或计划文档链接,可以直接关闭本 issue。

Contributor guide

Open the contributing guide

Research direction

Start with apps/mobile/src/session/selectableMarkdownHtml.ts and its hasMath/runtime injection path, then inspect MarkdownFileReader.tsx, mermaidWebViewHtml.ts, and richContentAssets.generated.ts. Use apps/mobile/src/__tests__/selectableMarkdownHtml.test.ts as the test entry point; done means Mermaid blocks render in the file preview with readable fallback source, while documents without Mermaid avoid loading the runtime and existing scrolling, highlighting, selection, and light/dark behavior remain intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
react-native, typescript
Domain
frontend, mobile
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.