feat(export): PDF 内嵌函数图像矢量图
- 抽取 render.py 共享几何:新增 PlotGeometry + compute_geometry,render_svg 改为薄序列化层,SVG 输出与重构前逐字节一致(8 组用例回归验证) - 新增 app/plot/render_reportlab.py:消费共享几何产出 reportlab 矢量 Drawing (网格/坐标轴 Line、曲线 PolyLine、刻度/标签 String、ylabel Group 旋转), 复用 STSong-Light 渲染中文,按页面内容宽 renderScale 缩放 - pdf.py _block_function_plot 改为内嵌矢量图(解析/渲染失败或超预算回退占位, 单图失败不阻断整篇);mermaid 仍占位 - 抽取 FunctionPlotBudget + format_plot_diagnostic 到 _common.py,html/pdf 共用 - 文档同步:PDF 已内嵌函数图像,DOCX 仍占位(栅格化范围外) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -15,16 +15,17 @@ backend/app/export/
|
||||
├── markdown.py mistune 'ast' renderer → Document AST
|
||||
├── exporters/
|
||||
│ ├── __init__.py
|
||||
│ ├── _common.py 共享工具(URL 协议校验 + 占位 warning 文案 + 元数据格式化)
|
||||
│ ├── _common.py 共享工具(URL 协议校验 + 函数图像预算 + 占位 warning 文案 + 元数据格式化)
|
||||
│ ├── html.py HtmlExporter(Document AST → 完整 HTML5)
|
||||
│ ├── pdf.py PdfExporter(Document AST → PDF,reportlab)
|
||||
│ └── docx.py DocxExporter(Document AST → DOCX,python-docx)
|
||||
└── service.py ExportService(注册表 + 后台渲染 + 取消 + 产物生命周期)
|
||||
|
||||
backend/app/plot/
|
||||
├── parser.py 函数图像表达式解析(白名单 AST)
|
||||
├── render.py FunctionPlot → 静态 SVG
|
||||
└── renderer.py StaticRenderer 内部契约(§10.4)
|
||||
├── parser.py 函数图像表达式解析(白名单 AST)
|
||||
├── render.py FunctionPlot → 共享几何(compute_geometry)+ 静态 SVG
|
||||
├── render_reportlab.py FunctionPlot → reportlab 矢量 Drawing(PDF 内嵌)
|
||||
└── renderer.py StaticRenderer 内部契约(§10.4)
|
||||
```
|
||||
|
||||
HTTP DTO(`ExportStatus` / `ExportFormat` / `ExportSource` / `ExportOptions` / `ExportJob` 等)放在 [app/contracts.py](../../backend/app/contracts.py),与 Benchmark DTO 同层;`DocumentNode` / `ExportResult` 属导出器内部协议,放在 `export/document.py`,不进入 HTTP 契约。
|
||||
@@ -62,9 +63,10 @@ fenced code 按语言分流:`mermaid` → `mermaid` 节点、`function_plot`/`
|
||||
|
||||
## PDF / DOCX 导出器(v1 文本优先)
|
||||
|
||||
`PdfExporter`(reportlab platypus)与 `DocxExporter`(python-docx)实现与 HtmlExporter 一致的同步 `render(document, options) -> ExportResult` + 异步 `export`。v1 为文本优先,覆盖标题/段落/行内强调与链接/列表/引用/表格/代码块/数学文本;`function_plot` 与 `mermaid` 保留源码占位并记 warning(与现有 Mermaid 处理一致)。
|
||||
`PdfExporter`(reportlab platypus)与 `DocxExporter`(python-docx)实现与 HtmlExporter 一致的同步 `render(document, options) -> ExportResult` + 异步 `export`。v1 为文本优先,覆盖标题/段落/行内强调与链接/列表/引用/表格/代码块/数学文本;`mermaid` 保留源码占位并记 warning。`function_plot` 在 PDF 中已内嵌为矢量图,在 DOCX 中仍保留源码占位并记 warning(DOCX 内嵌需栅格化,本轮范围外)。
|
||||
|
||||
- PDF 中文字体用 reportlab 内置 `STSong-Light` CID 字体,无外部字体依赖;CID 字体无独立 bold/italic 字重,行内强调退化为普通文本(内容不丢、样式简化),标题靠字号区分层级。
|
||||
- PDF 的 `function_plot` 经 `render_reportlab` 消费 `compute_geometry` 的共享几何,产出矢量 `Drawing`(网格/坐标轴 `Line`、曲线 `PolyLine`、刻度/标签 `String`,ylabel 用 `Group` 旋转),再按页面内容宽缩放追加到 story,与 HTML 的 SVG 视觉一致;解析/渲染失败或超预算时回退源码占位并记 warning,单图失败不阻断整篇。
|
||||
- DOCX 通过 Normal 样式挂载 `w:eastAsia=宋体` 保证中文显示,bold/italic 由 Word 原生渲染;链接写入可点击的 `w:hyperlink` run。
|
||||
- 扩展名/MIME:html→`.html`/`text/html`,pdf→`.pdf`/`application/pdf`,docx→`.docx`/`application/vnd.openxmlformats-officedocument.wordprocessingml.document`;路由 `FileResponse` 按 `mime_type` + `file_name` 通用化,无需改路由。
|
||||
|
||||
@@ -121,10 +123,11 @@ cd backend
|
||||
uv run pytest -q
|
||||
```
|
||||
|
||||
`tests/test_export.py` 覆盖 Markdown 解析(标题/行内/列表/代码分流/表格/数学)、HTML 渲染(标签 + 转义 + warning)、Service 端到端(note 源与 markdown 源、PDF/DOCX 魔法字节与 CJK 字体、引用块正文与嵌套列表顺序等结构内容回归、排队任务取消、未知 note、取消、list/get、过期 410)与 `ExportSource` 契约校验。`tests/test_plot.py` 覆盖表达式解析/求值、SVG 渲染与 `StaticRenderer` 契约(函数图像渲染、Mermaid 占位)。
|
||||
`tests/test_export.py` 覆盖 Markdown 解析(标题/行内/列表/代码分流/表格/数学)、HTML 渲染(标签 + 转义 + warning)、Service 端到端(note 源与 markdown 源、PDF/DOCX 魔法字节与 CJK 字体、引用块正文与嵌套列表顺序等结构内容回归、排队任务取消、未知 note、取消、list/get、过期 410)与 `ExportSource` 契约校验。`tests/test_plot.py` 覆盖表达式解析/求值、SVG 渲染、共享几何 `compute_geometry`、`render_reportlab` 矢量 Drawing(Line/PolyLine/String/Group、CJK 字体、y 翻转、缩放)与 `StaticRenderer` 契约(函数图像渲染、Mermaid 占位)。
|
||||
|
||||
## 范围外(后续 PR)
|
||||
|
||||
- PDF 内嵌函数图像与 Mermaid 渲染(v1 仅源码占位)。
|
||||
- Mermaid 静态渲染(后端无渲染能力,HTML/PDF/DOCX 均保留源码占位)。
|
||||
- DOCX 内嵌函数图像(需栅格化为 PNG,本轮范围外,仅 PDF 内嵌矢量图)。
|
||||
- 函数图像交互预览与缩放(前端 JS Renderer 负责,后端仅提供静态 SVG)。
|
||||
- 代码语法高亮(当前仅 CSS class 占位)。
|
||||
|
||||
Reference in New Issue
Block a user