1
0
Files
PPTX/openspec/changes/archive/2026-03-04-fix-multiline-text-font-size/design.md
lanyuanxiaoyao 5b367f7ef3 fix: 修复多行文本渲染时字号只应用于第一段的bug
当使用 YAML 多行字符串语法定义文本内容时,python-pptx 会自动
将包含换行符的文本分割成多个段落。修改 _render_text 方法使其
遍历所有段落并应用相同的字体样式(大小、粗体、斜体、颜色、对齐)。

主要变更:
- renderers/pptx_renderer.py: 将 p = tf.paragraphs[0] 改为 for p in tf.paragraphs
- tests/unit/test_renderers/test_pptx_renderer.py: 新增多行文本测试用例
- openspec/specs/element-rendering/spec.md: 更新 spec 文档
- openspec/changes/archive/: 归档完成的变更
2026-03-04 12:18:23 +08:00

100 lines
3.5 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.
## Context
当前 `renderers/pptx_renderer.py` 中的 `_render_text` 方法使用 `tf.paragraphs[0]` 来应用字体样式。当文本内容包含换行符时(如 YAML 多行字符串语法 `|`python-pptx 会自动创建多个段落,但样式只应用到第一个段落。
现有代码问题:
```python
# 创建文本框
textbox = slide.shapes.add_textbox(x, y, w, h)
tf = textbox.text_frame
tf.text = elem.content # 包含换行符时python-pptx 会创建多个段落
# 只对第一个段落应用样式 - 问题所在
p = tf.paragraphs[0]
if 'size' in elem.font:
p.font.size = Pt(elem.font['size']) # 只有第一个段落生效
```
测试验证(见 `temp/test_multiline_behavior.py`
- 当设置 `tf.text = "第一行\n第二行\n第三行"`
- `len(tf.paragraphs)` 返回 3
- 只有 `paragraphs[0].font.size` 被设置,其余为 `None`
## Goals / Non-Goals
**Goals:**
- 修复多行文本渲染时,字体样式只应用于第一段的问题
- 确保所有字体样式属性size, bold, italic, color, align应用到所有段落
- 保持单行文本的渲染行为不变
- 添加完整的单元测试覆盖
**Non-Goals:**
- 不支持不同段落使用不同样式(当前架构是一个文本框一个样式配置)
- 不修改 HTML 渲染器HTML 渲染器无此问题)
## Decisions
### 决策1遍历所有段落应用样式
选择遍历 `tf.paragraphs` 并对每个段落应用样式,而不是其他方案。
**替代方案考虑**
1. **逐段设置内容**`add_paragraph()`):需要重写整个文本设置逻辑,改动较大
2. **只对第一个段落设置**(当前行为):存在 bug不可接受
3. **遍历所有段落**(选择):最小改动,符合当前设计语义
**理由**
- 代码改动最小,只需将 `p = tf.paragraphs[0]` 改为 `for p in tf.paragraphs:`
- 符合当前设计语义:一个文本框使用统一的字体样式配置
- 向后兼容:单行文本只有一个段落,行为不变
### 决策2不增加新的配置选项
不添加类似 `apply_style_to_all_paragraphs` 的配置选项。
**理由**
- 这是 bug 修复,不是新功能
- 当前设计中,一个文本框就应该使用统一样式
- 添加配置会增加复杂度,且用途有限
### 决策3测试策略
在单元测试中新增多行文本测试用例,使用 Mock 验证样式应用到所有段落。
**理由**
- 现有测试只验证 `paragraphs[0]` 的样式
- 需要验证修复后的行为正确
- 测试应覆盖多种换行情况2行、3行、多行
## Risks / Trade-offs
### 风险1现有测试可能失败
**风险**:现有测试中 Mock 的 `paragraphs` 只有一个元素,改为遍历后可能通过但不完整。
**缓解**新增专门的多行文本测试Mock 返回多个段落对象。
### 风险2性能影响
**风险**:遍历所有段落可能对极多段落的文本有轻微性能影响。
**评估**:影响可忽略不计。通常文本框段落数量有限(<100遍历开销极小。
### 风险3空段落行为
**风险**:如果存在空段落(如连续换行),可能产生意外行为。
**评估**python-pptx 会自动处理空段落,样式设置到空段落无副作用。
## Migration Plan
无需迁移计划。这是 bug 修复:
- 向后兼容:单行文本行为完全不变
- 多行文本:从错误行为变为正确行为
- 无 API 变更
- 无配置变更
## Open Questions
无。这是一个明确且范围有限的 bug 修复。