1
0
Files
PPTX/openspec/specs/template-system/spec.md
lanyuanxiaoyao cd7988cbd5 feat: initial implementation of html2pptx with OpenSpec documentation
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(+)
2026-03-02 14:28:25 +08:00

189 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`,正常处理