fix: print PDF from actual editor theme CSS and shared Markdown rendering

This commit is contained in:
2026-09-07 14:33:19 +08:00
parent 9f097ea629
commit d1cbc10fc4
20 changed files with 530 additions and 43 deletions
+11
View File
@@ -167,3 +167,14 @@ PDF 使用导出按钮点击时的主题配色快照,支持六种内置/社区
PDF 取消导出源/产物大小限制、Mermaid 数量和像素预算、请求资源数量和字节预算、Vault 图片大小/累计预算、MathText 长度/深度预算、函数图数量/表达式数量及 AST 预算。HTML/DOCX、在线预览仍使用原有限制;有效图片、Vault 路径、表达式语法校验和数值求解退出条件仍生效。无限制指移除应用导出配额,实际文件规模仍受浏览器、解析器和可用内存约束。
关闭窗口仅结束 UI 生命周期,导出流程继续;主动取消仍取消提交中的后台任务。回归测试见 `ExportDialog.spec.ts``exportService.spec.ts``test_pdf_theme_resources.py`
### PDF 实际主题样式修正(2026-09-07
七色调色板加 ReportLab 固定排版不能复现笔记主题。应用界面的 PDF 导出现在提交 `print_html`:复用 Markdown 渲染器、KaTeX、Shiki、编辑器 DOM 容器、主题 CSS、CSS 变量、标题偏好和字体资源,由 Chromium 打印为可选择文本的 PDF。保留背景纹理、伪元素、边框、阴影和语义样式;打印规则只处理页面尺寸、滚动容器、分页、图表缩放和交互按钮。提示块采用编辑器的 blockquote 结构以匹配主题选择器。KaTeX 内部 SVG 不应用图表缩放规则。
`POST /api/exports/preview-resources` 根据同一 Markdown 快照准备 Vault 图片和函数图 SVG,不恢复 PDF 的旧资源配额。图片保留透明通道;不读取 Vault 外文件。客户端将字体和主题图片内嵌为 data URI。浏览器进程关闭文档 JavaScript、网络与文件资源加载,等待字体就绪后打印;不会为静态 CSS 加载用户脚本。
后端依赖 Playwright(已写入 pyproject/uv.lock)。Windows 优先使用本机 Edge/Chrome,可用 `APP_PDF_BROWSER` 指定可执行文件;没有系统浏览器时,在 backend 目录运行 `uv run playwright install chromium`。打印在独立子进程中执行,避免 Windows Uvicorn 事件循环冲突。
不传 print_html 的旧 API 客户端保留 ReportLab 兼容路径,其固定排版不能代表应用主题的实际样式。HTML/DOCX 导出行为不变。主题字体/图片需可从应用资源读取并内嵌,读取失败会报错,避免输出缺失资源却宣称样式一致。
@@ -0,0 +1,11 @@
# PDF 实际主题样式修复验收
路径:G:/OSProject/NotesAgent。此前七色调色板验收仅覆盖配色,不能代表完整主题样式一致;本次替换应用 PDF 导出的渲染链路。
- 使用真实主题 CSS、编辑器容器、伪元素、字体、标题偏好、KaTeX 与 ShikiChromium 输出 PDF;旧客户端 ReportLab 路径仅用于兼容。
- 纸间时光保留纸张边框、缝线、左侧装订线、顶部胶带、提示块与代码块装饰。修复跨页图表右侧裁切、提示块 DOM 选择器及 KaTeX 根号 SVG 受图表规则影响的问题。
- 无旧 PDF 数量/大小配额;内嵌资源、禁用文档脚本及网络访问、保留用户主动取消行为。
- 六主题各两页,由真实前端构造快照、实际后端导出、Poppler 渲染检查。样例和浏览器参考截图位于本机 .local-plans/pdf-browser。
- 后端全量 882 项、前端全量 451 项通过;最终排版调整后相关前端19项、资源/浏览器后端15项通过;生产构建成功。1 条既有 Starlette 警告和既有大分包提示保留。
- 浏览器烟测验证 CSS 伪元素文本进入 PDF,文档脚本未执行;Vault 越界图片被拒绝,17 条函数表达式可准备。
- 用户已有的三份笔记修改未纳入提交。
@@ -0,0 +1,50 @@
[
{
"theme": "paper-moments",
"pages": 2,
"bytes": 187968,
"sha256": "33a28768101307d97f950135bd8910907ab88df82174b87d4350bd02c71e3236",
"renderer": "Chromium / actual CSS snapshot",
"visual_review": "passed"
},
{
"theme": "light",
"pages": 2,
"bytes": 105426,
"sha256": "50bd5cfb9303c17d1b34fd5e7b3ed05915720dd45aba2dfa5623e4c387f273a6",
"renderer": "Chromium / actual CSS snapshot",
"visual_review": "passed"
},
{
"theme": "dark",
"pages": 2,
"bytes": 105445,
"sha256": "586da3acaf3f55ad802da13c188544a50347f1b58d2fbe2c20a22605d9d9e3d9",
"renderer": "Chromium / actual CSS snapshot",
"visual_review": "passed"
},
{
"theme": "sepia",
"pages": 2,
"bytes": 105471,
"sha256": "700bf49901ef23da7f760efba346a69a61f7ce4f3bb26b3b2e7ab673ecbd3809",
"renderer": "Chromium / actual CSS snapshot",
"visual_review": "passed"
},
{
"theme": "ocean-blue",
"pages": 2,
"bytes": 105414,
"sha256": "7501dc0765af583d498ed54c9678631d9e6578dcb68dbc6db9c0e83551cc3479",
"renderer": "Chromium / actual CSS snapshot",
"visual_review": "passed"
},
{
"theme": "midnight-purple",
"pages": 2,
"bytes": 105489,
"sha256": "213f59e4b43e701deda9e6b8589913c2d795d3ef8a642b516ba425aa1bd6da9e",
"renderer": "Chromium / actual CSS snapshot",
"visual_review": "passed"
}
]