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)
4.6 KiB
4.6 KiB
ADDED 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 应只需要:
- 在 core/elements.py 中定义新的 dataclass(如 VideoElement)
- 在
create_element()工厂函数中添加对应的分支 - 在各个渲染器中实现渲染方法
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