1
0
Files
lanyuanxiaoyao ed940f0690 refactor: modularize yaml2pptx into layered architecture
Refactor yaml2pptx.py from a 1,245-line monolithic script into a modular
architecture with clear separation of concerns. The entry point is now
127 lines, with business logic distributed across focused modules.

Architecture:
- core/: Domain models (elements, template, presentation)
- loaders/: YAML loading and validation
- renderers/: PPTX and HTML rendering
- preview/: Flask preview server
- utils.py: Shared utilities

Key improvements:
- Element abstraction layer using dataclass with validation
- Renderer logic built into generator classes
- Single-direction dependencies (no circular imports)
- Each module 150-300 lines for better readability
- Backward compatible CLI interface

Documentation:
- README.md: User-facing usage guide
- README_DEV.md: Developer documentation

OpenSpec:
- Archive refactor-yaml2pptx-modular change (63/70 tasks complete)
- Sync 5 delta specs to main specs (2 new + 3 updated)
2026-03-02 16:43:45 +08:00

4.8 KiB
Raw Permalink Blame History

Element Abstraction

Purpose

定义元素抽象层的规格,使用 dataclass 实现类型安全的元素数据类,支持创建时验证和未来扩展。

Requirements

Requirement: 元素必须使用 dataclass 定义

系统必须使用 Python dataclass 定义所有元素类型TextElement, ImageElement, ShapeElement, TableElement提供类型安全和自动生成的方法。

Scenario: 文本元素使用 dataclass 定义

  • WHEN 开发者查看 core/elements.py 中的 TextElement 类
  • THEN 应使用 @dataclass 装饰器定义,包含 type、content、box、font 字段

Scenario: 图片元素使用 dataclass 定义

  • WHEN 开发者查看 core/elements.py 中的 ImageElement 类
  • THEN 应使用 @dataclass 装饰器定义,包含 type、src、box 字段

Scenario: 形状元素使用 dataclass 定义

  • WHEN 开发者查看 core/elements.py 中的 ShapeElement 类
  • THEN 应使用 @dataclass 装饰器定义,包含 type、shape、box、fill、line 字段

Scenario: 表格元素使用 dataclass 定义

  • WHEN 开发者查看 core/elements.py 中的 TableElement 类
  • THEN 应使用 @dataclass 装饰器定义,包含 type、data、position、col_widths、style 字段

Requirement: 元素必须在创建时进行验证

系统必须在元素对象创建时(__post_init__ 方法)进行数据验证,确保元素数据的有效性,尽早发现错误。

Scenario: 文本元素验证 box 字段

  • WHEN 创建 TextElement 对象时 box 字段不是包含 4 个数字的列表
  • THEN 系统应抛出 ValueError 异常,提示 "box 必须包含 4 个数字"

Scenario: 图片元素验证 src 字段

  • WHEN 创建 ImageElement 对象时 src 字段为空
  • THEN 系统应抛出 ValueError 异常,提示 "图片元素必须指定 src"

Scenario: 形状元素验证 box 字段

  • WHEN 创建 ShapeElement 对象时 box 字段不是包含 4 个数字的列表
  • THEN 系统应抛出 ValueError 异常,提示 "box 必须包含 4 个数字"

Scenario: 表格元素验证 data 字段

  • WHEN 创建 TableElement 对象时 data 字段为空列表
  • THEN 系统应抛出 ValueError 异常,提示 "表格数据不能为空"

Requirement: 必须提供元素工厂函数

系统必须提供 create_element(elem_dict) 工厂函数,从字典创建对应类型的元素对象,统一元素创建入口。

Scenario: 从字典创建文本元素

  • WHEN 调用 create_element({'type': 'text', 'content': 'Hello', 'box': [1, 1, 8, 1]})
  • THEN 系统应返回 TextElement 对象,包含相应的字段值

Scenario: 从字典创建图片元素

  • WHEN 调用 create_element({'type': 'image', 'src': 'image.png', 'box': [1, 1, 4, 3]})
  • THEN 系统应返回 ImageElement 对象,包含相应的字段值

Scenario: 从字典创建形状元素

  • WHEN 调用 create_element({'type': 'shape', 'shape': 'rectangle', 'box': [1, 1, 2, 1]})
  • THEN 系统应返回 ShapeElement 对象,包含相应的字段值

Scenario: 从字典创建表格元素

  • WHEN 调用 create_element({'type': 'table', 'data': [['A', 'B'], ['1', '2']], 'position': [1, 1]})
  • THEN 系统应返回 TableElement 对象,包含相应的字段值

Scenario: 不支持的元素类型

  • WHEN 调用 create_element({'type': 'unknown'})
  • THEN 系统应抛出异常,提示不支持的元素类型

Requirement: 元素类型必须支持未来扩展

系统的元素抽象层设计必须支持未来添加新元素类型(如 VideoElement只需定义新的 dataclass 和在工厂函数中添加分支。

Scenario: 添加新元素类型的步骤清晰

  • WHEN 开发者需要添加新元素类型(如 Video
  • THEN 应只需要:
    1. 在 core/elements.py 中定义新的 dataclass如 VideoElement
    2. create_element() 工厂函数中添加对应的分支
    3. 在各个渲染器中实现渲染方法

Scenario: 新元素类型不影响现有元素

  • WHEN 添加新元素类型
  • THEN 现有元素类型Text, Image, Shape, Table的行为不应受到影响

Requirement: 元素数据类必须提供默认值

系统必须为元素数据类的可选字段提供合理的默认值,简化元素创建。

Scenario: 文本元素的默认值

  • WHEN 创建 TextElement 对象时不提供 box 和 font 字段
  • THEN 系统应使用默认值box=[1, 1, 8, 1]font={}

Scenario: 图片元素的默认值

  • WHEN 创建 ImageElement 对象时不提供 box 字段
  • THEN 系统应使用默认值box=[1, 1, 4, 3]

Scenario: 形状元素的默认值

  • WHEN 创建 ShapeElement 对象时不提供 fill 和 line 字段
  • THEN 系统应使用默认值或 None