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

3.5 KiB
Raw Blame History

Context

当前 renderers/pptx_renderer.py 中的 _render_text 方法使用 tf.paragraphs[0] 来应用字体样式。当文本内容包含换行符时(如 YAML 多行字符串语法 |python-pptx 会自动创建多个段落,但样式只应用到第一个段落。

现有代码问题:

# 创建文本框
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 修复。