Files
MorphDoc/docs/PROGRESS.md
T

626 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Markdown PDF 导出器进度
最后更新:2026-07-27
## 1. 当前概况
项目目录:
```text
C:\Projects\md-to-pdf
```
当前分支:
```text
main
```
已有提交:
```text
b459def fix: 修复预览与 PDF 渲染边界问题
d93728b feat: 完善 Mermaid 配置与预览缩放
d1b5880 feat: 实现 Chromium PDF 导出与精确预览
d625523 fix: 修复长文档分页与滚动同步
1d93f31 feat: 实现真实分页预览
52cf816 feat: 完善导出设置与打印预览
ec14f79 feat: 扩展本地主题兼容能力
fa07472 feat: 实现网页实时预览
7224dfd feat: 实现 Markdown 渲染核心
ec48bce chore: 初始化项目骨架
```
最新阶段已完成 Markdown ECharts YAML 围栏、统一 SVG 渲染与分页,
并完善默认示例、源文本收起、顶栏文档状态和快速页码跳转。
`v0.4.0` 桌面端阶段已经完成:共享应用服务、无 Server 的 Electron
运行时、三套内置主题、统一品牌资源、Windows 安装包以及 Docker Compose
发布候选均已通过验证。
## 2. 已完成
### 2.1 项目骨架
- 建立 npm workspaces。
- 建立 React + Vite 前端。
- 建立 Fastify 后端。
- 建立 `packages/core` 共享包。
- 建立主题、测试和 Docker 目录。
- 初始化本地 Git 仓库。
### 2.2 导出配置模型
`packages/core/src/export-config.ts` 已包含:
- 版本 3 配置模型;
- A3、A4、A5、Letter、Legal、Tabloid 和自定义纸张;
- 横向、纵向;
- 四边页边距;
- 页眉和页脚左右中区域;
- 页码位置和格式;
- PDF 元数据;
- 打印背景、缩放和一级标题分页选项;
- Mermaid 布局、主题、外观和字体;
- Zod 数据校验;
- 默认 A4 技术文档预设。
### 2.3 主题接口
`packages/core/src/theme.ts``themes/typora-like` 和动态主题注册器已包含:
- 版本化主题清单;
- 主题 ID、名称、版本、作者、许可证;
- DOM 预设;
- 支持能力声明;
- 可选基础 CSS、主体 CSS 和打印 CSS
- 自制 Typora 风格主题;
- `#write` 兼容文档结构;
- 内置主题和 `.local/themes` 本地主题动态扫描;
- 按基础 CSS、主体 CSS、打印 CSS 的固定顺序组合;
- 主题内相对 CSS `@import` 安全展开;
- 主题 CSS 相对资源重写与受限资源接口;
- 目录匹配、真实路径包含关系和外部 URL 安全检查。
内置主题包含项目自有的 Typora 风格主题,以及按公司内部私有项目决策
复制的 GitHub、Pixyll 和 Whitey 三套 Typora 默认主题。三套复制主题的
来源和内部使用边界记录在 `themes/INTERNAL_THEME_NOTICE.md`;如未来公开、
商用或向公司外部分发,必须重新完成许可证审查。
### 2.4 Markdown 渲染核心
提交 `7224dfd` 已完成:
- `packages/renderer` 独立工作区;
- Front Matter 解析;
- Markdown 到安全 HTML
- 标题锚点;
- 表格;
- 任务列表;
- 脚注;
- highlight.js 代码高亮;
- KaTeX 数学公式;
- Mermaid 安全占位;
- sanitize-html 安全过滤;
- 元数据规范化;
- 功能检测;
- 统一 `<article id="write">` 输出;
- 5 项渲染单元测试。
### 2.5 网页实时预览
提交 `fa07472` 已完成:
- 可测试的 Fastify `buildApp()`
- `POST /api/render` 服务端统一 Markdown 渲染;
- 动态主题清单、CSS 和资源 API;
- Markdown 编辑及本地 `.md` 文件读取;
- 250ms 防抖 A4 实时预览;
- iframe 隔离主题 CSS
- KaTeX、highlight.js 和按需加载的 Mermaid
- 桌面双栏与移动端上下布局;
- 5 项渲染器测试和 4 项后端测试。
### 2.6 主题兼容增强
提交 `ec14f79` 已完成:
- 主题清单可选基础 CSS
- 基础 CSS、主体 CSS、打印 CSS 固定组合顺序;
- 安全的相对 CSS `@import` 展开和资源 URL 重写;
- CSS 导入深度、循环、外部 URL 和越界路径检查;
- GitHub、Pixyll 和 Whitey 三套本地 Typora 白色主题导入;
- 可恢复替换和默认防覆盖;
- 主题开发指南;
- 后端测试增至 6 项。
### 2.7 导出设置与打印预览
提交 `52cf816` 已完成:
- 导出配置升级到版本 3,并兼容迁移版本 2 浏览器缓存;
- 纸张收敛为 A3、A4、A5、US-Letter 和 US-Legal
- 默认 A4 纵向和 16mm 四边页边距;
- 统一 96 CSS px/in、72 PDF pt/in 和 25.4mm/in 的物理单位换算;
- 响应式导出设置抽屉;
- 纸张、方向、页边距、页眉、页码和主题的版本化浏览器缓存;
- 页眉左中右内容和变量;
- 五种页码样式、对齐和起始页码;
- Mermaid 官方配置 frontmatter、默认主题与错误隔离;
- Mermaid 全局 Dagre/ELK 布局、官方主题、外观和字体设置;
- Markdown 表格对齐属性保留和自适应列宽;
- 纸张尺寸和页边距实时预览。
## 3. Chromium PDF 导出与精确预览
### 3.1 Chromium PDF 导出
- 引入固定版本 Playwright Chromium。
- 新增 `POST /api/pdf`,复用服务端 Markdown 渲染结果、`#write` DOM、主题 CSS、打印 CSS 和统一分页运行时。
- PDF 文本可搜索,支持中文、长表格、KaTeX、Mermaid、页眉、页脚和页码。
- Chromium 浏览器实例复用,每个请求使用独立 BrowserContext。
- 支持浏览器预热、并发门控、排队上限、超时和关闭清理。
- 仅允许同源、`data:``blob:``about:` 资源,阻止 PDF 页面访问外部网络。
- PDF 响应提供安全的 UTF-8 文件名、页数、Mermaid 错误数和 `Server-Timing`
- 前端“导出 PDF”按钮已启用,生成完成后直接下载。
### 3.2 快速预览与精确预览
- 快速预览继续使用 Paged.js,适合编辑时即时反馈。
- 精确预览直接复用 `/api/pdf` 结果,确保显示页数和最终下载一致。
- 快速与精确模式可以切换,PDF 缓存按 Markdown、主题和导出配置失效。
- PDF.js 使用集中渲染队列,当前可见页优先,滚动方向上的相邻页次优先。
- 远离视口的 Canvas 延迟释放,避免 65 页长文档持续占用大尺寸位图内存。
- 未完成渲染的页面显示白色占位,Canvas 完成后才显示,消除快速滚动时的黑影。
- 编辑区和两种预览模式支持按滚动比例同步定位。
### 3.3 Mermaid 分页性能优化
- Mermaid 仍使用官方渲染器、配置 frontmatter、严格安全模式、默认主题和 classic 样式。
- 渲染完成后记录 SVG 与容器的实际小数宽高,将 SVG 转为内嵌 Data URL 图片再交给 Paged.js 分页。
- 静态 SVG 仍由 Chromium 以矢量和可搜索文字输出,不发生位图化。
- 快速预览和 PDF 默认使用相同的静态 SVG;`mermaid-output=inline-svg` 仅保留为内部诊断开关。
- 65 页、67 个 Mermaid 的附件中,分页耗时约从 2.60 秒降至 1.29 秒,总生成耗时约降低 12.7%。
- A/B PDF 均为 65 页,逐页 61,102 个非空白字符和 11,762 个文本项完全一致。
### 3.4 PDF 性能观测
- 记录排队、浏览器、上下文、导航、文档渲染、Mermaid、资源等待、分页、PDF 打印和总耗时。
- `Server-Timing` 已暴露上述关键阶段,包括 `mermaid-conversion`
- 65 页附件的主要耗时来自 Mermaid 渲染、Paged.js 分页和 Chromium PDF 打印。
- PDF 缓冲区直接返回,避免无意义的二次 `Buffer` 复制。
### 3.5 AIO 容器部署
- 使用多阶段 Dockerfile 构建前端、后端和共享包。
- 基于 Node.js 22 Debian 构建运行镜像,并由项目锁定的 Playwright
`1.62.0` 安装精确匹配的 Chromium 与系统依赖。
- 单容器内由 Nginx 提供前端并代理 Fastify API。
- Playwright 通过同一 Nginx 地址加载精确预览运行时。
- 容器以非 root `pwuser` 运行并提供 1 GiB 共享内存。
- Compose 支持端口、只读主题目录、PDF 并发、队列和超时配置。
- 增加容器健康检查和统一进程退出处理。
- Nginx 显式以 JavaScript MIME 类型提供 PDF.js `.mjs` Worker。
### 3.6 Mermaid 配置与预览缩放
- Mermaid 固定为 `11.16.0`ELK 使用官方
`@mermaid-js/layout-elk@0.2.2` 并按需加载核心布局代码。
- 全局导出设置支持 Dagre、ELK、官方主题、Classic、Hand-drawn、Neo
外观和自定义本地字体。
- 单图 `config` Front Matter 可以覆盖全局布局、主题、外观、字体、
`themeVariables` 和图表专属配置。
- `style``classDef``linkStyle` 保持 Mermaid 原生语义。
- `themeCSS`、严格安全模式和资源限制不能由 Markdown 覆盖。
- Mermaid 与 Paged.js 计算期间隐藏分页 iframe,避免显示官方渲染器的
临时测量节点。
- 快速预览和精确预览共用 50%~400% 显示缩放,支持滑块、手动输入、
100% 重置和独立浏览器缓存。
- 缩放不进入导出配置,不改变分页或 PDF;精确预览会按显示宽度重绘
邻近 Canvas,保持文字清晰。
### 3.7 渲染边界修复与复用重构
- PDF 总超时覆盖 Chromium 启动、上下文创建、页面渲染和有界清理,
浏览器预热也受同一超时约束。
- 当前预览模式的重复点击不再触发无意义的状态重置和 PDF 请求。
- Mermaid 分页测量使用实际主题、字体和盒模型,静态 SVG 图片锁定实际
小数尺寸,避免测量容器宽度与真实纸张不一致。
- 非法 Front Matter 在预览和 PDF API 中统一返回 400;无效本地主题
会被隔离并记录警告,不影响其他主题。
- `packages/core` 统一维护 Markdown 文档、分页载荷、分页结果和耗时类型,
前端快速预览与后端 PDF 使用同一个载荷构造函数。
- 前端 Markdown 防抖渲染与主题清单/CSS 加载已从 `App.tsx` 抽取为独立
Hook,保留原有取消请求和错误隔离行为。
- 主题注册表增加 1 秒目录扫描缓存和主动失效接口,减少同一请求链路中
重复遍历主题目录,同时兼顾本地主题热更新。
- CSS 像素与 PDF 点数换算只使用 core 中的共享常量;删除已经不参与协议
或逻辑的 `contentHeight` 字段。
### 3.8 Windows 显示缩放与快速预览分页差异
- 此前 65 页长文档在快速预览中生成 64 页、在精确预览和最终 PDF 中
生成 65 页;该差异并非由 Chromium 版本不同导致。
- 出现差异时,笔记本内屏使用 Windows 150% 系统显示缩放。切换到使用
100% 显示缩放的外接显示器后,快速预览与精确预览的分页结果基本一致。
- 当前定位是:Windows 显示缩放改变浏览器的 `devicePixelRatio`,并可能
影响字体栅格化和 CSS 布局中的子像素取整;单处差异很小,但会在长文档
分页过程中累计,最终造成页数差异。
- 精确预览直接展示服务端 Chromium 生成的 PDF,最终下载也复用同一结果,
因此精确预览和最终 PDF 继续作为权威分页结果;快速预览定位为编辑期间的
客户端近似分页,不承诺在所有显示缩放环境下与 PDF 页数完全一致。
- 后续优化快速预览时,应重点检查 `devicePixelRatio`、浏览器页面缩放、
字体度量和逐页高度取整;分页测量不得依赖物理像素,视觉缩放不得参与
文档排版和分页计算,并避免逐页取整造成累计误差。
- 后续分页回归应覆盖 Windows 100%、125% 和 150% 系统显示缩放,分别
记录快速预览、精确预览和最终 PDF 的页数及分页边界。
### 3.9 Markdown ECharts 图表
- 新增可独立复用的 `packages/markdown-echarts` 工作区,为 Markdown-it
提供安全的 `echarts` YAML 围栏。
- 围栏支持版本、固定高度或宽高比、主题、图注和 ECharts `option`
高度默认 80mm,主题默认跟随文档。
- 当前支持 line、bar、scatter、pie、radar、heatmap、boxplot 和
candlestick 系列,并校验各系列的数据结构和必要坐标系。
- 每个系列必须使用非空 `series[].data``dataset.source` 或具有有效
上游数据的内置 transform;缺少数据等错误会显示包含配置路径的局部
占位,不中断整篇 Markdown。
- YAML 会转换为安全纯数据对象;禁止函数、自定义标签、锚点和别名、
外部 URL、HTML formatter、原型污染属性及 `custom` 系列。
- 浏览器按需加载 ECharts 模块,以 SVG 渲染,并可冻结为内联 SVG 或
SVG Data URL 图片;快速预览与 PDF 使用同一套运行时。
- 分页遵循 Mermaid 的不可拆分规则:当前页空间足够时原位放置,不足时
移到下一页,超高图表等比例缩放到单页内,不跨页切割。
- PDF 输出等待 ECharts、Mermaid、字体和图片全部完成后再分页,并分别
返回 ECharts 与 Mermaid 错误数量。
- 包内 README 已记录围栏语法、默认值、验证规则、错误行为、安全边界、
Markdown-it 接入和浏览器渲染方式。
### 3.10 工作区布局与页码导航
- 默认 Markdown 示例新增 ECharts 柱状图,打开网页即可验证 YAML 围栏、
SVG 渲染和分页。
- 文件名及渲染、分页、导出错误状态从源文本标题栏迁移到顶部应用标题
旁,长文件名支持省略和完整悬停提示。
- 源文本区域支持收起和展开;桌面端收起为 48px 左侧窄栏,预览区扩展
到剩余宽度并保持纸张居中,窄屏收起为 44px 顶部横条。
- 折叠内容使用真实 `display:none`,不会残留可聚焦文本框或进入无障碍
树;按钮提供 `aria-controls``aria-expanded`
- 当前页从预览标题行移到缩放工具栏左侧,显示为
`第 [n] / 总页数 页`,避免重复信息。
- 页码输入支持 Enter 和失焦提交,自动限制到 1~总页数;空值和非法
小数恢复当前页。
- 快速预览直接定位 iframe 内 `.pagedjs_page`;精确预览定位
`.precise-pdf-page`。滚动预览时输入框同步当前页。
- 精确预览会动态识别桌面内部滚动容器或窄屏主窗口滚动容器,目标页顶端
与实际可视滚动区域对齐。
- 快速预览 iframe 只负责生成分页内容并回传自然高度,滚动统一交给外层
`.preview-scroll`;滚动条因此与精确预览一样贴在右侧预览容器边缘,
不再贴着居中的纸张右边缘。
- 快速预览的页码识别和跳转会合并外层滚动位置、iframe 位置、内部分页
位置与显示缩放比例,50%~400% 视觉缩放不会破坏页码同步。
### 3.11 ECharts 第二阶段图表
- ECharts 系列支持从首版 8 种扩展到 17 种,新增 `tree``treemap`
`sunburst``graph``sankey``chord``funnel``gauge`
`pictorialBar`
- 当前使用 ECharts 6.1.0`chord` 直接采用 ECharts 6 官方和弦图及
`ChordChart` 按需模块,不引入第三方扩展。
- `tree``treemap``sunburst` 校验递归层级结构;矩形树图和旭日图
的叶节点必须提供有限数值。
- `graph``sankey``chord` 校验节点、关系边、端点引用与边权重;
Graph 未指定布局时,有完整坐标则使用 `none`,否则默认使用 `force`
- `funnel``gauge` 校验有限数值数据;`pictorialBar` 复用柱图的数据和
坐标轴规则,并允许不加载外部资源的 `path://` 内嵌矢量路径。
- 安全策略新增层级节点、关系节点和关系边数量限制,继续禁止外部图片、
跳转链接、函数、HTML formatter 和原型污染属性。
- 默认 Markdown 现在包含基础柱状图及九种第二阶段图表,每种均使用独立
YAML 围栏,可直接编辑和观察 SVG、分页及错误占位行为。
- Treemap 默认示例关闭节点下钻和面包屑,显式启用父级与叶节点标签,并
增加白色分隔边框,避免扁平数据区域缺少辨识信息或底部控件占用空间。
- Markdown/PDF 属于确定性的静态输出场景,浏览器引擎会在全局和系列级
强制关闭 ECharts 动画、动画延迟和持续时间,不允许 YAML 动画参数使
预览或 PDF 停留在动画中间帧。
### 3.12 v0.4.0 Electron 桌面端
- 新增 `apps/desktop` Electron 43.2.0 工作区,使用 Electron Forge
7.11.2 打包。
- 根项目版本升级为 `0.4.0`Vite 从根 `package.json` 注入统一版本,
工具标题右侧显示 `v0.4.0` 徽标。
- 应用窗口和 PDF 窗口均关闭 Node Integration,启用 Context Isolation
和 Chromium Sandbox,并使用不同 preload 暴露窄 IPC 接口。
- 桌面端 PDF 直接接收 Web 端已经构造的共享分页载荷,复用现有
`PagedDocumentRuntime`、主题 CSS、Mermaid 和 ECharts 运行时。
- 隐藏 PDF 窗口使用 Electron 自带 Chromium 的
`webContents.printToPDF()`,桌面发行包不携带 Playwright Chromium。
- Paged.js 的帧队列在纯隐藏窗口中不会推进;桌面 PDF 任务期间使用
计时器调度分页队列,分页完成后恢复原生 `requestAnimationFrame`
- Chromium 打印前将透明、不可聚焦、不进入任务栏的 PDF 窗口短暂放到
屏幕外,使复杂分页页面拥有可打印的窗口表面,用户不会看到该窗口。
- PDF Buffer 通过受控 IPC 返回 Web 界面,桌面端使用系统“另存为”对话框
写入文件;Web 版继续使用浏览器下载行为。
- 生产页面通过 `mdpdf://bundle/` 自定义安全协议加载,不使用权限过宽的
`file://`PDF Session 只允许同源、`data:``blob:``about:`
资源。
- Windows x64 未签名目录包、Squirrel `Setup.exe` 和 ZIP 已由 Forge
成功生成;`app.asar` 只包含
编译后的主进程、preload 和清单,Web 静态资源作为只读资源单独打包。
- 新增 `packages/application`,统一封装 Markdown 渲染、主题清单、主题
CSS 和主题资源读取;Fastify 仅作为 HTTP 适配器。
- Web 端通过应用后端抽象选择 HTTP 或 Electron IPC;桌面端通过受限 IPC
直接调用共享服务,不启动 Fastify,不占用本地 HTTP 端口。
- 主题资源通过 `mdpdf://theme/` 安全协议提供,应用窗口与独立 PDF
Session 均完成协议注册和来源限制。
- 修复 Electron 主进程 ESM Bundle 中 YAML 依赖动态加载 `process`
失败的问题,构建时注入 Node `createRequire`
- `logos/` 作为统一品牌源:Web 使用 favicon、Apple Touch Icon 和
Web ManifestElectron 使用 ICO、ICNS、窗口图标和安装器图标。
- Forge 输出目录包含版本号,正式内部交付使用 Squirrel `Setup.exe`
ZIP 作为免安装辅助包;当前未签名。
### 3.13 v0.4.0 内置主题与发布产物
- `.local/themes` 中 GitHub、Pixyll 和 Whitey 三套主题已复制到
`themes/`,从 v0.4.0 起随 Web 容器和桌面安装包内置。
- 内置主题注册优先于相同 ID 的本地主题,避免 Compose 默认挂载旧副本
覆盖发布版本,并记录可诊断警告。
- Windows 正式安装包为
`Markdown PDF 导出器-0.4.0 Setup.exe`,约 137.48 MiBSHA-256 为
`9C12F9A007E102BDB5213ABC5246F4480083FCA5D67DCD45354728BCFDB54220`
- 中文产品名、窗口标题、安装包和开始菜单名称保持不变,Windows 主程序
与进程文件固定为 `md-to-pdf.exe`;目录包和 Squirrel NUPKG 均已验证。
- 本地镜像为 `yixiong/md-to-pdf:v0.4.0`Compose 容器保持健康运行并
监听 `http://localhost:8080`
- Dockerfile 默认保留完整 Playwright Chromium 安装路径,同时支持通过
构建参数复用本机已验证的旧版本运行层,适合内网软件源较慢的环境。
## 4. 已执行验证
2026-07-27 在当前完整工作区成功执行:
```text
npm test
npm run typecheck
npm run build
git diff --check
```
结果:
- ECharts 围栏测试:36 项通过;
- 共享配置测试:9 项通过;
- 渲染器测试:10 项通过;
- 应用服务测试:5 项通过;
- 前端测试:67 项通过;
- 后端测试:29 项通过;
- 桌面端测试:7 项通过;
- 全项目共 163 项测试通过;
- 全项目类型检查通过;
- 生产构建通过;
- `git diff --check` 通过。
Electron 桌面端第一阶段验证结果:
- Electron 43.2.0 应用窗口成功加载现有 React/Vite 界面,标题旁正确显示
`v0.4.0`
- 最小 Markdown 通过隐藏 Electron Chromium 生成 1 页、52,308 字节
PDF,文字可搜索,并通过桌面原生保存通道落盘。
- 默认示例通过桌面端生成 4 页、439,501 字节 A4 PDFMermaid 和
10 个 ECharts 图表错误数均为 0。
- 将默认示例全部 4 页渲染为 PNG 后逐页检查,Tree、Treemap、Sunburst、
Graph、Sankey、Chord、Funnel、Gauge 和 PictorialBar 均完整显示,
未发现空白页、黑块、跨页切割或明显裁切。
- PDF.js 可以从 4 页中提取 670 个非空白字符,各页均包含可搜索文字。
- Forge 成功生成 Windows x64 未签名目录包,生产窗口通过
`mdpdf://bundle/index.html` 加载,版本徽标和界面静态资源正常。
- 精简后的 `app.asar` 约 554 KiB,Web 静态资源共 134 个文件、约
9.0 MiB;运行目录只包含 Electron 自带的一套 Chromium。
已使用浏览器插件完成视觉验证:
- 默认示例中的 ECharts 柱状图生成 1 个内联 SVG,无错误占位;
- 顶栏文件名、分页状态与操作按钮在桌面和窄屏均无重叠;
- 桌面端源文本收起后宽度从 576px 降为 48px,预览区从 864px 扩展
到 1392px;窄屏折叠条为 44px
- 快速预览输入第 2 页后目标页顶端对齐 iframe 视口,滚动回首页和第二页
时输入框分别同步为 1 和 2
- 页码输入 0 和 99 时分别限制到 1 和总页数;
- 精确预览输入第 2 页后,目标页与桌面滚动容器顶部误差为 0;
- 快速预览改用外层滚动容器后,右侧容器边界为 1440px,纸张边界约为
1400px,滚动条稳定贴在容器最右侧而非纸张边缘;
- 快速预览输入第 1 页后目标页与外层可视区域顶部误差为 0,外层滚动到
第 2 页时页码输入框同步更新为 2;
- 快速预览在 50% 和 150% 下的可滚动高度分别随内容显示高度缩放,
iframe 自身保持无滚动;切换精确/快速模式后仍使用同一右侧滚动条;
- 桌面端收起源文本后,预览滚动容器从 48px 延伸至窗口右边缘,纸张仍
在扩展后的预览区域内居中;
- 窄屏精确预览自动使用主窗口滚动,并正确跳转到第 2 页;
- 页码控件在窄屏独占首行,缩放控件在下一行铺满,没有与预览模式或主题
选择器重叠;
- 当前默认 Markdown 和主题资源加载正常,快速预览生成 2 页;
- 编辑 Markdown 后标题、表格、Mermaid 和分页状态均完成防抖重绘;
- 从本地 GitHub 主题切换到内置 Typora 风格主题后 iframe 正常重建;
- 本轮浏览器回归期间控制台无警告或错误;
- 预览缩放在 50%、100%、150% 和 400% 下均按比例显示,快速与精确
预览的分页结果不受缩放影响;
- 包含 ELK、Base 主题、Hand-drawn 外观、自定义字体、
`themeVariables``style``classDef` 的 Mermaid 样例在快速预览
与精确预览中均成功渲染;
- 在 Windows 150% 系统显示缩放的笔记本内屏上,65 页附件的快速预览
生成 64 页,67 个 Mermaid 全部使用静态 SVG
- 同一附件的精确预览和最终 PDF 均为 65 页;
- 切换到 Windows 100% 系统显示缩放的外接显示器后,快速预览与精确预览
的分页结果基本一致,进一步排除了 Chromium 版本差异这一判断方向;
- 精确预览快速跳转至第 46、47、65 页,无黑色 Canvas、空白页或渲染错误;
- PDF.js 同时只保留视口邻近页面的 Canvas,远端页面资源可以释放;
- Mermaid A/B PDF 页数、逐页文字和抽样视觉结果一致;
- 抽查第 2、6、27、53、65 页,Mermaid 尺寸、分页位置和末页内容正常。
ECharts 第二阶段浏览器与 PDF 验证结果:
- 默认示例生成 10 个 ECharts SVG,包含原柱状图和九种新增系列,错误
占位数为 0,浏览器控制台无警告或错误;
- 快速预览生成 6 页,第 2~6 页各放置两张完整图表,所有图表边界均位于
当前页内容区内,没有跨页切割;
- 精确预览同样生成 6 页,逐页跳转正常;Chord、Funnel、Gauge 和
PictorialBar 的 PDF Canvas 视觉检查通过;
- 使用默认导出配置调用 PDF API 生成 4 页 PDF,响应中的 ECharts 和
Mermaid 错误数均为 0
- PDF 中九种新增图表的标题均可搜索;将全部页面渲染为 PNG 后,Tree、
Treemap、Sunburst、Graph、Sankey、Chord、Funnel、Gauge 和
PictorialBar 均显示完整,未发现裁切、重叠、黑块或空白图表。
- 修正 Treemap 示例后再次检查快速与精确预览:底部下钻面包屑已隐藏,
五个叶节点边界清晰;SVG 中父级和叶节点共 7 个标签均处于可见状态。
- 进一步确认此前 Treemap 标签虽存在于 SVG,但被冻结在入场动画初始帧,
`fill-opacity` 约为 `0.000014`,肉眼近似完全透明;全局关闭动画后,
快速预览和精确 PDF 中的 2 个父级及 5 个叶节点标签均清晰可见。
2026-07-27 已重新构建并启动本地发布候选镜像:
- 使用完整多阶段 `deploy/Dockerfile` 构建
`yixiong/md-to-pdf:v0.3.0`,镜像大小约 612 MB
- Compose 强制重建后容器健康检查通过,服务继续监听
`http://localhost:8080`
- 首页返回 200`POST /api/render` 的 ECharts 冒烟请求返回
`code``echarts` 功能标识和 `md-echarts` 安全占位;
- 容器内 `@md-to-pdf/markdown-echarts` 工作区包可正常加载;
- 当前镜像已通过发布前手动验收,并作为 `v0.3.0` 发布镜像保留运行。
此前主题阶段已使用浏览器插件完成视觉验证:
- 导入并打开 `tmp/数据中台项目周报_2026_W30.md`
- 参考 `tmp/数据中台项目周报_2026_W30.pdf` 的 Typora 输出;
- GitHub、Pixyll 和 Whitey 三套保留的本地主题均可正常切换;
- 三套主题中的表格均为 `border-collapse: collapse`、单元格间距为 0,并铺满 `#write` 内容宽度;
- GitHub 表格边框颜色与主题定义的 `#dfe2e5` 一致;
- Open Sans、PT Serif 和 Merriweather 字体资源均成功加载;
- KaTeX、代码高亮和 Mermaid 正常显示;
- 浏览器控制台无警告或错误。
2026-07-26 已在 Docker Desktop 完成 AIO 容器验证:
- Docker Compose 配置展开、镜像构建、启动、健康检查和重启恢复通过;
- 运行镜像约 611 MBNode.js、Nginx、Fastify 和 Chromium 均以非
root UID 999 运行;
- Nginx 首页、分页运行页、API、主题 CSS 和 PDF.js Worker 均正常;
- 默认只读挂载识别 1 个内置主题和 3 个本地主题;
- 周报通过容器导出为 4 页,附件通过容器导出为 65 页,Mermaid
错误数均为 0
- 两份 PDF 的所有页面均包含可搜索文字,附件共提取 68,434 个字符;
- 抽查周报第 1、4 页和附件第 1、33、65 页,未发现裁切、重叠、
黑块或空白页;
- 浏览器快速预览、主题切换、精确 PDF.js 预览和导出交互通过;
- 修复 Nginx 缺少 `.mjs` MIME 映射导致精确预览 Worker 加载失败的问题。
`v0.3.0` 发布验收完成后,已停止并删除本项目 Compose 容器及网络以释放
本地资源;`yixiong/md-to-pdf:v0.3.0` 镜像继续保留。
2026-07-27 已构建并启动 `v0.3.1` 发布候选:
- 使用完整多阶段 Dockerfile 构建 `yixiong/md-to-pdf:v0.3.1`,镜像
大小约 612 MB
- Compose 容器使用该镜像运行并通过健康检查,服务监听
`http://localhost:8080`
- 容器首页返回 200,默认 Markdown 解析出 10 个 ECharts 围栏,
错误占位和渲染警告均为 0
- 容器生成的默认配置 PDF 为 4 页、约 521 KiBECharts 和 Mermaid
渲染错误数均为 0
- ECharts 已编译进按需加载的前端浏览器 Bundle,生产运行时不需要保留
独立的 `echarts` Node.js 包;
- 当前容器保留运行,等待 `v0.3.1` 发布前手动验收。
2026-07-27 已完成 `v0.4.0` 最终发布候选验证:
- 生成本地镜像 `yixiong/md-to-pdf:v0.4.0`,镜像内容 ID 为
`sha256:1bf4a136e9b822fa0925070cd522ea2adbad8b388d8e039d6509024d466666b3`
- Compose 强制替换为 v0.4.0 后健康检查通过,首页返回 200,健康接口
返回 `ok`,主题接口返回 4 个 `bundled` 主题;
- 容器 Chromium 生成中文、表格、KaTeX、代码和 Mermaid 验收 PDF
HTTP 200、1 页、147,374 字节,Mermaid/ECharts 错误数均为 0
- PDF 渲染为 PNG 后检查通过,中文、公式、表格、代码、图表、页边距和
页码均正常,无裁切、重叠、黑块或空白;
- Compose 网页真实加载后标题旁显示 `v0.4.0`,主题选择器包含 4 个内置
主题,多页预览和图表正常,浏览器控制台无错误;
- Forge Squirrel 安装包、NUPKG 和 ZIP 均已生成,安装包约 137.48 MiB,
当前 Authenticode 状态为未签名。
## 5. 当前注意事项
- `output/` 可能包含本地 PDF 验证产物,已被 Git 忽略,不得提交。
- `apps/web/src/App.tsx` 负责分页 iframe 生命周期和父页面消息处理。
- `apps/web/src/use-markdown-render.ts` 负责 Markdown 防抖请求、取消和
渲染错误状态。
- `apps/web/src/use-theme-resources.ts` 负责主题清单、主题 CSS 和请求取消。
- `apps/web/src/paged-document-runtime.ts` 是快速预览和 PDF 共用的 Mermaid、资源等待和 Paged.js 分页运行时。
- `apps/web/src/paged-preview-frame.ts` 负责 iframe 消息协议和运行目标选择。
- `apps/web/src/paged-preview.ts` 负责分页协议、共享文档 CSS、页眉和页码 CSS。
- `apps/web/src/mermaid-page-fit.ts` 负责超高 Mermaid 的单页等比例适配。
- `apps/web/src/mermaid-static-image.ts` 负责锁定 Mermaid 盒模型并转换为静态矢量 SVG 图片。
- `apps/web/src/paged-table-handler.ts` 负责跨页表格表头处理。
- `apps/web/src/PrecisePdfPreview.tsx``pdf-render-queue.ts` 负责 PDF.js 精确预览和 Canvas 生命周期。
- `apps/web/src/PreviewPageControl.tsx``preview-page.ts` 负责当前页输入、
页码边界、滚动页识别和快速跳转。
- `apps/web/src/preview-zoom.ts``PreviewZoomControl.tsx` 负责预览缩放缓存、边界和控制界面。
- `packages/markdown-echarts` 负责 ECharts YAML 协议、验证、安全过滤、
Markdown-it 插件、浏览器 SVG 渲染和分页样式。
- `apps/server/src/pdf-engine.ts` 负责 Chromium 生命周期、并发、网络限制、分页调用和 PDF 输出。
- `apps/web/src/ExportSettingsDrawer.tsx` 是导出设置界面。
- `apps/web/src/export-settings.ts` 负责版本化浏览器缓存。
- `packages/core/src/export-config.ts` 是纸张、页边距、页眉页脚和页码的共享模型。
- `packages/core/src/document.ts` 是渲染文档、分页载荷、运行结果和耗时的
共享模型。
- `apps/server/src/app.ts` 是新增的可测试 Fastify 应用。
- `packages/application` 负责共享 Markdown 渲染和主题应用服务;
`apps/server``apps/desktop` 分别提供 HTTP 和 IPC 适配。
- `apps/desktop/src/main.ts` 负责 Electron 生命周期、自定义应用协议、
应用窗口、IPC 校验和原生 PDF 保存。
- `apps/desktop/src/electron-pdf-generator.ts` 负责隐藏 PDF 窗口、分页
调度、网络限制、打印和窗口复用。
- `apps/desktop/src/app-preload.ts``pdf-preload.ts` 分别定义应用
窗口和 PDF 运行窗口的最小 IPC 能力。
- `.local/themes/typora-*` 仍可作为用户本机副本;v0.4.0 的三套发布版本
已复制到 `themes/` 并标记为内置主题。
- `.local/theme-backups` 中保留 GitHub、Pixyll 和 Whitey 的可恢复备份;Newsprint 和 Night 的当前副本及备份已按用户要求删除。
- Typora 复制主题按公司内部私有项目决策内置,不面向外部公开或商用;
未来改变分发范围前必须重新完成许可证审查。
- 快速预览会受到客户端 Windows 显示缩放、浏览器缩放和设备像素比影响;
对页数和分页边界有严格要求时,以精确预览和最终 PDF 为准。
- 资源目录上传、本地相对图片、临时目录和路径安全尚未实现。
- 桌面端已通过进程内共享服务实现离线 Markdown 渲染、主题读取和 PDF
导出,不依赖 Fastify 或本地 HTTP Server。
- v0.4.0 AIO 容器已经通过 Docker Desktop 构建、端到端和浏览器验证,
当前 Compose 容器保持运行。
## 6. 推荐接手顺序
### 阶段一:桌面文档工作区与资源安全
- Markdown 文件夹或 ZIP
- 相对图片解析;
- 每请求独立临时目录;
- 路径穿越和符号链接越界防护;
- 文件数量、单文件大小、总大小和超时限制;
- 请求结束可靠清理。
### 阶段二:导出配置扩展
- Front Matter 元数据覆盖;
- 浏览器本地配置预设;
- 配置 JSON 导入和导出。
## 7. 首版验收目标
- 可以选择或粘贴 Markdown
- 网页正确预览常用 Markdown、公式、Mermaid 和 ECharts
- 可以下载真实 PDF
- PDF 文本可搜索;
- 预览与 PDF 基本一致;
- 支持 A4、Letter、方向和边距;
- 支持基础页眉、页脚和页码;
- 支持主题切换扩展;
- 相对图片可用;
- 转换后不保留用户文档;
- Docker Compose 可在内网启动。