当使用 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/: 归档完成的变更
100 lines
3.5 KiB
Markdown
100 lines
3.5 KiB
Markdown
## 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 修复。
|