Add core Python script (yaml2pptx.py) for converting YAML to PowerPoint: - Element rendering: text, image, shape, table, chart - Template system with placeholders - PPTX generation with python-pptx OpenSpec workflow setup: - 3 archived changes: browser-preview, template-dir-cli, yaml-to-pptx - 7 main specifications covering all core modules - Config and documentation structure 30 files changed, 4984 insertions(+)
7.2 KiB
7.2 KiB
Template System
Purpose
Template system 提供可复用的幻灯片布局和样式定义。模板包含变量定义、元素列表,支持变量替换、条件渲染,以及从目录加载。颜色和样式直接在模板中定义,无需额外的主题抽象层。
Requirements
Requirement: 模板必须定义变量列表
模板 SHALL 包含 vars 字段,定义该模板需要的变量,包括变量名、是否必需、默认值等。
Scenario: 加载模板变量定义
- WHEN 模板文件定义了
vars列表,包含name、required、default等字段 - THEN 系统成功加载变量定义,可通过模板对象访问
Scenario: 验证必需变量
- WHEN 模板定义了
{name: title, required: true}的变量 - THEN 渲染时如果未提供该变量,系统抛出错误
Scenario: 使用变量默认值
- WHEN 模板定义了
{name: subtitle, required: false, default: ""}的变量 - THEN 渲染时如果未提供该变量,系统使用空字符串作为默认值
Requirement: 模板必须定义元素列表
模板 SHALL 包含 elements 字段,定义该模板的幻灯片布局和元素。
Scenario: 加载模板元素定义
- WHEN 模板文件定义了
elements列表,包含文本、图片、形状等元素 - THEN 系统成功加载元素列表,准备渲染
Scenario: 元素包含模板变量引用
- WHEN 模板元素中包含
{title}等模板变量引用 - THEN 系统在渲染时用用户提供的值替换变量
Scenario: 元素直接指定样式值
- WHEN 模板元素中直接指定
color: "#4a90e2"等样式值 - THEN 系统正确应用该样式值
Requirement: 系统必须支持模板渲染
系统 SHALL 能够根据用户提供的变量值渲染模板,生成实际的元素列表。
Scenario: 渲染包含变量的模板
- WHEN 用户提供
{title: "Hello", subtitle: "World"}渲染模板 - THEN 系统将模板中的
{title}替换为 "Hello",{subtitle}替换为 "World"
Scenario: 数值类型自动转换
- WHEN 模板定义
size: "{font_size}"且用户提供{font_size: "44"} - THEN 系统自动将字符串 "44" 转换为整数 44
Scenario: 检测未定义的模板变量
- WHEN 模板中引用了
{undefined_var},但该变量未在 vars 中定义,也未由用户提供 - THEN 系统抛出错误,指出未定义的变量
Requirement: 系统必须支持条件渲染
系统 SHALL 支持基于变量值的条件渲染,通过 visible 字段控制元素是否显示。
Scenario: 显示满足条件的元素
- WHEN 元素定义了
visible: "{subtitle != ''}\",且用户提供了非空的 subtitle - THEN 系统渲染该元素
Scenario: 隐藏不满足条件的元素
- WHEN 元素定义了
visible: "{subtitle != ''}\",但用户提供的 subtitle 为空字符串 - THEN 系统跳过该元素,不渲染到幻灯片中
Scenario: 条件表达式语法错误
- WHEN visible 字段包含无效的条件表达式
- THEN 系统抛出错误,提示条件表达式格式错误
Requirement: 模板文件必须可从指定目录加载
系统 SHALL 从用户通过 --template-dir 参数指定的目录加载模板文件,支持通过模板名称引用。模板名称必须是纯文件名,不能包含路径分隔符。
Scenario: 通过名称加载模板
- WHEN 幻灯片指定
template: title-slide,且用户提供--template-dir /path/to/templates - THEN 系统从
/path/to/templates/title-slide.yaml加载模板文件
Scenario: 模板文件不存在时报错
- WHEN 幻灯片引用不存在的模板名称
- THEN 系统抛出错误,提示"模板文件不存在: <模板名>",并显示查找位置和期望文件路径
Scenario: 缓存已加载的模板
- WHEN 多个幻灯片使用同一个模板
- THEN 系统仅加载一次模板文件,后续使用缓存
Scenario: 错误信息包含详细的查找信息
- WHEN 模板文件未找到
- THEN 错误信息包含:模板名称、查找位置(template_dir)、期望文件的完整路径、解决建议
Requirement: 系统必须支持自定义幻灯片
系统 SHALL 支持不使用模板,直接定义元素的自定义幻灯片。
Scenario: 渲染自定义幻灯片
- WHEN 幻灯片未指定
template字段,直接包含elements列表 - THEN 系统跳过模板渲染,直接处理元素列表
Scenario: 自定义幻灯片中直接指定样式
- WHEN 自定义幻灯片的元素直接指定
color: "#4a90e2" - THEN 系统正确应用该颜色值
Scenario: 自定义幻灯片和模板混合使用
- WHEN 演示文稿中部分幻灯片使用模板,部分为自定义
- THEN 系统正确处理两种类型的幻灯片
Requirement: 模板变量解析必须深度递归
系统 SHALL 递归解析模板元素的所有嵌套字段中的变量引用。
Scenario: 解析嵌套对象中的变量
- WHEN 模板元素定义了
font: {size: "{font_size}", color: "{text_color}"} - THEN 系统正确解析嵌套对象中的所有变量引用
Scenario: 解析数组中的变量
- WHEN 模板元素定义了
box: ["{left}", 2, 8, 3] - THEN 系统正确解析数组中的变量引用
Scenario: 解析多层嵌套的变量
- WHEN 模板包含复杂的嵌套结构,多层使用变量引用
- THEN 系统递归解析所有层级的变量,直到无变量引用为止
Requirement: 模板名称必须是纯文件名
系统 SHALL 验证模板名称不包含路径分隔符,确保模板只能从指定目录的一层加载。
Scenario: 拒绝包含正斜杠的模板名称
- WHEN 幻灯片指定
template: subdir/title-slide - THEN 系统抛出错误,提示"模板名称不能包含路径分隔符: subdir/title-slide"
Scenario: 拒绝包含反斜杠的模板名称
- WHEN 幻灯片指定
template: subdir\title-slide - THEN 系统抛出错误,提示"模板名称不能包含路径分隔符: subdir\title-slide"
Scenario: 拒绝路径遍历尝试
- WHEN 幻灯片指定
template: ../other-templates/slide - THEN 系统抛出错误,提示模板名称不能包含路径分隔符
Scenario: 接受纯文件名
- WHEN 幻灯片指定
template: title-slide(不包含路径分隔符) - THEN 系统正常处理,从指定的 template_dir 加载模板
Scenario: 错误信息提供正确格式示例
- WHEN 系统因模板名称包含路径分隔符而报错
- THEN 错误信息中包含"模板名称应该是纯文件名,如: 'title-slide'"的提示
Requirement: 未指定模板目录时必须报错
系统 SHALL 在用户未提供 --template-dir 参数但 YAML 文件中使用了模板时,立即报错。
Scenario: 使用模板但未指定目录
- WHEN YAML 文件中包含
template: title-slide,但templates_dir参数为None - THEN 系统在尝试加载模板时抛出错误,提示"未指定模板目录,无法加载模板"
Scenario: 不使用模板时不检查目录
- WHEN YAML 文件中所有幻灯片都是自定义幻灯片(不包含
template字段) - THEN 系统不检查
templates_dir是否为None,正常处理