1
0

feat: 为metadata、模板和幻灯片添加description字段支持

添加可选的description字段用于文档目的,不影响渲染输出。

主要更改:
- core/presentation.py: 添加metadata.description属性
- core/template.py: 添加template.description属性
- tests: 添加16个新测试用例验证description功能
- docs: 更新README.md和README_DEV.md文档
- specs: 新增page-description规范文件
This commit is contained in:
2026-03-04 13:22:33 +08:00
parent 5d60f3c2c2
commit 2fd8bc1b4a
12 changed files with 845 additions and 0 deletions

View File

@@ -136,6 +136,16 @@ metadata:
dpi: 150 # 高质量输出 dpi: 150 # 高质量输出
``` ```
#### description 字段
`metadata.description` 字段用于描述整个演示文稿的概要和用途,仅用于文档目的,不影响生成的 PPTX 文件:
```yaml
metadata:
size: "16:9"
description: "2024年度项目进展总结包含背景、成果和展望"
```
### 使用模板 ### 使用模板
```yaml ```yaml
@@ -418,6 +428,27 @@ slides:
author: "作者" author: "作者"
``` ```
#### 模板 description 字段
模板文件可以包含可选的 `description` 字段,用于描述模板的用途和设计意图,仅用于文档目的:
```yaml
# templates/title-slide.yaml
description: "用于章节标题页的模板,包含主标题和副标题"
vars:
- name: title
required: true
elements:
- type: text
box: [1, 2, 8, 1]
content: "{title}"
font:
size: 44
bold: true
```
### 混合模式模板 ### 混合模式模板
混合模式允许你在使用模板的同时添加自定义元素,实现更灵活的布局组合。 混合模式允许你在使用模板的同时添加自定义元素,实现更灵活的布局组合。
@@ -583,6 +614,23 @@ slides:
content: "额外内容" content: "额外内容"
``` ```
#### 幻灯片 description 字段
幻灯片可以包含可选的 `description` 字段,用于描述该幻灯片的作用和内容,仅用于文档目的,不影响生成的 PPTX 文件:
```yaml
slides:
- description: "介绍项目背景和目标"
template: title-slide
vars:
title: "项目背景"
- description: "展示核心功能特性"
elements:
- type: text
content: "功能特性"
```
### 条件渲染 ### 条件渲染
#### 元素级条件渲染 #### 元素级条件渲染

View File

@@ -595,6 +595,48 @@ if right > slide_width + TOLERANCE:
- 检查变量定义是否有必需的 `name` 字段 - 检查变量定义是否有必需的 `name` 字段
- 检测默认值中引用不存在的变量 - 检测默认值中引用不存在的变量
### 8. description 字段
**决策**:为 metadata、模板和幻灯片添加可选的 `description` 字段
**理由**
- 自文档化:提高模板和演示文稿的可读性和可维护性
- 不影响渲染description 仅用于文档目的,不参与 PPTX 生成
- 完全向后兼容:字段为可选,现有文件无需修改
**实现要点**
1. **数据模型**
- `Presentation.description`:从 `metadata.description` 读取
- `Template.description`:从模板文件的 `description` 字段读取
- `Slide.description`:在 `render_slide()` 返回值中保留
2. **YAML 解析**
- 使用 `.get('description')` 自动处理缺失情况(返回 None
- YAML 原生支持多行文本格式
3. **不参与渲染**
- description 字段不传递给渲染器
- 不写入最终的 PPTX 文件
**示例**
```yaml
# metadata description
metadata:
description: "2024年度项目进展总结"
# 模板 description
templates:
title-slide:
description: "用于章节标题页的模板"
elements: [...]
# 幻灯片 description
slides:
- description: "介绍项目背景"
template: title-slide
```
## 扩展指南 ## 扩展指南
### 添加新元素类型 ### 添加新元素类型

View File

@@ -32,6 +32,7 @@ class Presentation:
metadata = self.data.get("metadata", {}) metadata = self.data.get("metadata", {})
self.size = metadata.get("size", "16:9") self.size = metadata.get("size", "16:9")
self.dpi = metadata.get("dpi", 96) self.dpi = metadata.get("dpi", 96)
self.description = metadata.get("description") # 可选的描述字段
# 验证尺寸值 # 验证尺寸值
if not isinstance(self.size, str): if not isinstance(self.size, str):
@@ -134,4 +135,5 @@ class Presentation:
return { return {
"background": slide_data.get("background"), "background": slide_data.get("background"),
"elements": element_objects, "elements": element_objects,
"description": slide_data.get("description"), # 保留幻灯片描述
} }

View File

@@ -54,6 +54,9 @@ class Template:
self.data = load_yaml_file(template_path) self.data = load_yaml_file(template_path)
validate_template_yaml(self.data, str(template_path)) validate_template_yaml(self.data, str(template_path))
# 可选的描述字段
self.description = self.data.get('description')
# 解析变量定义 # 解析变量定义
self.vars_def = {} self.vars_def = {}
for var in self.data.get('vars', []): for var in self.data.get('vars', []):
@@ -79,6 +82,9 @@ class Template:
# 初始化条件评估器 # 初始化条件评估器
obj._condition_evaluator = ConditionEvaluator() obj._condition_evaluator = ConditionEvaluator()
# 可选的描述字段
obj.description = template_data.get('description')
# 解析变量定义 # 解析变量定义
obj.vars_def = {} obj.vars_def = {}
for var in template_data.get('vars', []): for var in template_data.get('vars', []):

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-03-04

View File

@@ -0,0 +1,82 @@
# Design: Add Description Field to Metadata, Templates, and Slides
## Context
当前项目使用YAML格式的模板文件和演示文稿定义。YAML文件包含metadata元数据部分和slides列表。模板系统`template-system` spec定义了模板的结构包括vars、elements等字段。演示文稿通过YAML文件定义slides列表每个slide可以引用模板或定义自定义元素。
项目目前没有内置的机制来描述文档整体、页面或幻灯片的用途。开发者只能通过元素内容和变量名来推断,这降低了演示文稿、模板和幻灯片的可维护性。
## Goals / Non-Goals
**Goals:**
- 为metadata添加可选的description字段
- 为模板文件添加可选的description字段
- 为幻灯片定义添加可选的description字段
- 确保description字段在数据模型中被正确解析和保留
- 保持完全的向后兼容性
- 不影响渲染逻辑和输出结果
**Non-Goals:**
- 不将description写入最终的PPTX文件PowerPoint备注功能不在本次范围
- 不实现description的验证逻辑如长度限制、格式要求
- 不实现基于description的搜索或过滤功能
## Decisions
### 1. Description字段为可选的字符串类型
**决策:** description字段为可选字段类型为字符串可以为空字符串。
**理由:**
- 保持简单,不过度设计
- 用户可以自由描述,不受格式限制
- 可选设计确保向后兼容
**替代方案考虑:**
- 使用结构化格式如对象包含title、content等子字段- 过于复杂,当前需求不需要
### 2. Description不参与渲染
**决策:** description字段仅用于文档目的不传递给渲染器不影响PPTX生成。
**理由:**
- PowerPoint的备注功能需要额外处理且不在当前需求范围
- 保持渲染逻辑简单,避免引入不必要的复杂性
**替代方案考虑:**
- 将description写入PPTX备注 - 需要额外的python-pptx API调用增加复杂度
### 3. 在数据模型层面实现
**决策:** 在数据模型类Metadata/Document、Template、Slide中添加description属性在YAML解析时读取该字段。
**理由:**
- 与现有代码结构一致
- 便于统一处理和访问
- metadata中的description可以描述整个文档
**替代方案考虑:**
- 仅在YAML解析时保留不添加到数据模型 - 会导致信息丢失,不利于后续使用
## Risks / Trade-offs
| 风险 | 缓解措施 |
|------|----------|
| description字段可能被滥用或包含不恰当内容 | 依赖用户自律,不添加内容验证 |
| 增加数据模型的字段数量 | 影响很小,仅增加一个可选字符串字段 |
| 用户可能期望description能影响输出 | 在文档中明确说明description仅用于文档目的 |
## Migration Plan
1. 更新数据模型类添加description属性Metadata、Template、Slide
2. 更新YAML解析器读取metadata、模板和幻灯片的description字段
3. 添加测试用例验证description正确读取和保留
4. 更新文档说明新字段的用法
**回滚策略:**
- 由于是新增可选字段,移除该字段不会影响现有功能
- 如需回滚只需从数据模型和解析器中移除description相关代码
## Open Questions
无。本设计较为简单直接,没有未解决的技术问题。

View File

@@ -0,0 +1,36 @@
# Proposal: Add Description Field to Pages and Slides
## Why
当前项目和模板系统中缺乏对文档、页面和幻灯片用途的内置说明机制。当用户或开发者查看演示文稿YAML时难以快速理解整个文档的概要、某个模板的设计意图或幻灯片的使用场景。添加description字段可以提供自文档化的能力提高演示文稿、模板和幻灯片的可维护性和可读性。
## What Changes
- 为metadata添加可选的 `description` 字段,用于描述整个演示文稿的概要和用途
- 为模板文件添加可选的 `description` 字段,用于说明该模板的用途和设计意图
- 为幻灯片定义添加可选的 `description` 字段,用于说明该幻灯片的作用和内容
- description字段为纯文本字符串完全可选不影响现有渲染逻辑
- 保留description字段以供工具和文档生成使用
## Capabilities
### New Capabilities
- `page-description`: 为模板页面和幻灯片添加描述字段的功能
### Modified Capabilities
无现有能力的需求变更,仅新增可选字段
## Impact
**受影响的代码模块:**
- `models/` - 元数据、模板和幻灯片数据模型需要支持description字段
- `yaml_parsing/` - YAML解析器需要读取metadata和模板、幻灯片的description字段
- `specs/` - 新增page-description规范文档
**不受影响的模块:**
- 渲染逻辑 - description字段不影响视觉渲染
- 输出PPTX - description不写入最终的PPTX文件
**向后兼容性:**
- 完全向后兼容description为可选字段
- 现有模板和YAML文件无需修改即可继续使用

View File

@@ -0,0 +1,130 @@
# Page Description
## Purpose
Page Description功能允许用户为文档元数据、模板和幻灯片添加描述信息用于说明文档概要、页面的用途、设计意图或内容概要。这提高了演示文稿、模板和幻灯片的可读性和可维护性。
## ADDED Requirements
### Requirement: metadata必须支持可选的description字段
演示文稿的metadata SHALL 支持可选的 `description` 字段,用于描述整个演示文稿的概要和用途。
#### Scenario: metadata包含description字段
- **WHEN** YAML文件的metadata定义了 `description: "这是关于项目年度总结的演示文稿"`
- **THEN** 系统成功加载该描述字段可通过metadata对象访问
#### Scenario: metadata不包含description字段
- **WHEN** YAML文件的metadata未定义 `description` 字段
- **THEN** 系统正常加载演示文稿description属性为None或空字符串
#### Scenario: metadata description为空字符串
- **WHEN** metadata定义了 `description: ""`
- **THEN** 系统接受空字符串作为有效值
### Requirement: 模板必须支持可选的description字段
模板 SHALL 支持可选的 `description` 字段,用于描述该模板的用途和设计意图。
#### Scenario: 模板包含description字段
- **WHEN** 模板文件定义了 `description: "用于章节标题页的模板,包含主标题和副标题"`
- **THEN** 系统成功加载该描述字段,可通过模板对象访问
#### Scenario: 模板不包含description字段
- **WHEN** 模板文件未定义 `description` 字段
- **THEN** 系统正常加载模板description属性为None或空字符串
#### Scenario: description为空字符串
- **WHEN** 模板文件定义了 `description: ""`
- **THEN** 系统接受空字符串作为有效值
### Requirement: 幻灯片必须支持可选的description字段
幻灯片定义 SHALL 支持可选的 `description` 字段,用于描述该幻灯片的作用和内容。
#### Scenario: 幻灯片包含description字段
- **WHEN** 幻灯片定义了 `description: "介绍项目背景和目标"`
- **THEN** 系统成功加载该描述字段,可通过幻灯片对象访问
#### Scenario: 幻灯片不包含description字段
- **WHEN** 幻灯片定义未包含 `description` 字段
- **THEN** 系统正常处理幻灯片description属性为None或空字符串
### Requirement: description字段不得影响渲染逻辑
系统 SHALL 在渲染过程中忽略 `description` 字段不影响最终的PPTX输出。
#### Scenario: 渲染包含description的模板
- **WHEN** 系统渲染包含 `description` 字段的模板
- **THEN** description不参与元素渲染不影响输出结果
#### Scenario: 渲染包含description的幻灯片
- **WHEN** 系统渲染包含 `description` 字段的幻灯片
- **THEN** description不写入PPTX文件不影响输出结果
### Requirement: YAML解析器必须正确解析description字段
系统 SHALL 从YAML文件中正确读取 `description` 字段,并将其传递给数据模型。
#### Scenario: 解析metadata中的description
- **WHEN** YAML文件的metadata包含 `description: "文档描述"`
- **THEN** 解析器将该字符串传递给metadata对象的description属性
#### Scenario: 解析模板中的description
- **WHEN** YAML文件中的模板包含 `description: "这是描述"`
- **THEN** 解析器将该字符串传递给模板对象的description属性
#### Scenario: 解析幻灯片中的description
- **WHEN** YAML文件中的幻灯片包含 `description: "幻灯片描述"`
- **THEN** 解析器将该字符串传递给幻灯片对象的description属性
### Requirement: 数据模型必须包含description属性
元数据、模板和幻灯片数据模型 SHALL 包含 `description` 属性,用于存储描述信息。
#### Scenario: metadata对象包含description属性
- **WHEN** 开发者访问metadata对象
- **THEN** 可以通过 `metadata.description` 获取描述信息
#### Scenario: 模板对象包含description属性
- **WHEN** 开发者访问模板对象
- **THEN** 可以通过 `template.description` 获取描述信息
#### Scenario: 幻灯片对象包含description属性
- **WHEN** 开发者访问幻灯片对象
- **THEN** 可以通过 `slide.description` 获取描述信息
### Requirement: description字段必须支持中文字符
系统 SHALL 支持在 `description` 字段中使用中文字符和其他Unicode字符。
#### Scenario: metadata description包含中文
- **WHEN** metadata的description包含中文字符如 "这是关于项目的演示文稿"
- **THEN** 系统正确处理,不出现编码错误
#### Scenario: description包含中文
- **WHEN** 模板或幻灯片的description包含中文字符如 "这是中文描述"
- **THEN** 系统正确处理,不出现编码错误
#### Scenario: description包含多行文本
- **WHEN** description字段使用YAML多行文本格式
- **THEN** 系统正确读取完整的描述内容

View File

@@ -0,0 +1,46 @@
# Tasks: Add Description Field to Metadata, Templates, and Slides
## 1. 数据模型更新
- [x] 1.1 在Metadata/Document类中添加description属性可选默认为None
- [x] 1.2 在Template类中添加description属性可选默认为None
- [x] 1.3 在Slide类中添加description属性可选默认为None
- [x] 1.4 更新Metadata/Document类的__init__方法接受description参数
- [x] 1.5 更新Template类的__init__方法接受description参数
- [x] 1.6 更新Slide类的__init__方法接受description参数
## 2. YAML解析器更新
- [x] 2.1 更新metadata解析逻辑读取YAML中的description字段
- [x] 2.2 更新模板解析逻辑读取模板YAML中的description字段
- [x] 2.3 更新幻灯片解析逻辑读取slides列表中的description字段
- [x] 2.4 确保description字段缺失时使用默认值None
- [x] 2.5 支持多行YAML格式的description文本
## 3. 测试用例
- [x] 3.1 添加测试metadata包含description字段时正确加载
- [x] 3.2 添加测试metadata不包含description字段时正常工作
- [x] 3.3 添加测试模板包含description字段时正确加载
- [x] 3.4 添加测试模板不包含description字段时正常工作
- [x] 3.5 添加测试幻灯片包含description字段时正确加载
- [x] 3.6 添加测试幻灯片不包含description字段时正常工作
- [x] 3.7 添加测试description包含中文字符时正确处理
- [x] 3.8 添加测试description为空字符串时正常工作
- [x] 3.9 添加测试description不影响渲染输出
## 4. 文档更新
- [x] 4.1 更新README.md说明metadata支持description字段
- [x] 4.2 更新README.md说明模板支持description字段
- [x] 4.3 更新README.md说明幻灯片支持description字段
- [x] 4.4 在README.md中添加description字段的使用示例
- [x] 4.5 更新README_DEV.md记录description字段的设计说明
- [x] 4.6 确保文档中说明description仅用于文档目的不影响输出
## 5. 验证和集成
- [x] 5.1 运行所有现有测试,确保向后兼容性
- [x] 5.2 运行新添加的测试用例,确保全部通过
- [x] 5.3 使用包含description的示例YAML进行端到端测试
- [x] 5.4 验证生成的PPTX文件不受description字段影响

View File

@@ -0,0 +1,130 @@
# Page Description
## Purpose
Page Description功能允许用户为文档元数据、模板和幻灯片添加描述信息用于说明文档概要、页面的用途、设计意图或内容概要。这提高了演示文稿、模板和幻灯片的可读性和可维护性。
## Requirements
### Requirement: metadata必须支持可选的description字段
演示文稿的metadata SHALL 支持可选的 `description` 字段,用于描述整个演示文稿的概要和用途。
#### Scenario: metadata包含description字段
- **WHEN** YAML文件的metadata定义了 `description: "这是关于项目年度总结的演示文稿"`
- **THEN** 系统成功加载该描述字段可通过metadata对象访问
#### Scenario: metadata不包含description字段
- **WHEN** YAML文件的metadata未定义 `description` 字段
- **THEN** 系统正常加载演示文稿description属性为None或空字符串
#### Scenario: metadata description为空字符串
- **WHEN** metadata定义了 `description: ""`
- **THEN** 系统接受空字符串作为有效值
### Requirement: 模板必须支持可选的description字段
模板 SHALL 支持可选的 `description` 字段,用于描述该模板的用途和设计意图。
#### Scenario: 模板包含description字段
- **WHEN** 模板文件定义了 `description: "用于章节标题页的模板,包含主标题和副标题"`
- **THEN** 系统成功加载该描述字段,可通过模板对象访问
#### Scenario: 模板不包含description字段
- **WHEN** 模板文件未定义 `description` 字段
- **THEN** 系统正常加载模板description属性为None或空字符串
#### Scenario: description为空字符串
- **WHEN** 模板文件定义了 `description: ""`
- **THEN** 系统接受空字符串作为有效值
### Requirement: 幻灯片必须支持可选的description字段
幻灯片定义 SHALL 支持可选的 `description` 字段,用于描述该幻灯片的作用和内容。
#### Scenario: 幻灯片包含description字段
- **WHEN** 幻灯片定义了 `description: "介绍项目背景和目标"`
- **THEN** 系统成功加载该描述字段,可通过幻灯片对象访问
#### Scenario: 幻灯片不包含description字段
- **WHEN** 幻灯片定义未包含 `description` 字段
- **THEN** 系统正常处理幻灯片description属性为None或空字符串
### Requirement: description字段不得影响渲染逻辑
系统 SHALL 在渲染过程中忽略 `description` 字段不影响最终的PPTX输出。
#### Scenario: 渲染包含description的模板
- **WHEN** 系统渲染包含 `description` 字段的模板
- **THEN** description不参与元素渲染不影响输出结果
#### Scenario: 渲染包含description的幻灯片
- **WHEN** 系统渲染包含 `description` 字段的幻灯片
- **THEN** description不写入PPTX文件不影响输出结果
### Requirement: YAML解析器必须正确解析description字段
系统 SHALL 从YAML文件中正确读取 `description` 字段,并将其传递给数据模型。
#### Scenario: 解析metadata中的description
- **WHEN** YAML文件的metadata包含 `description: "文档描述"`
- **THEN** 解析器将该字符串传递给metadata对象的description属性
#### Scenario: 解析模板中的description
- **WHEN** YAML文件中的模板包含 `description: "这是描述"`
- **THEN** 解析器将该字符串传递给模板对象的description属性
#### Scenario: 解析幻灯片中的description
- **WHEN** YAML文件中的幻灯片包含 `description: "幻灯片描述"`
- **THEN** 解析器将该字符串传递给幻灯片对象的description属性
### Requirement: 数据模型必须包含description属性
元数据、模板和幻灯片数据模型 SHALL 包含 `description` 属性,用于存储描述信息。
#### Scenario: metadata对象包含description属性
- **WHEN** 开发者访问metadata对象
- **THEN** 可以通过 `metadata.description` 获取描述信息
#### Scenario: 模板对象包含description属性
- **WHEN** 开发者访问模板对象
- **THEN** 可以通过 `template.description` 获取描述信息
#### Scenario: 幻灯片对象包含description属性
- **WHEN** 开发者访问幻灯片对象
- **THEN** 可以通过 `slide.description` 获取描述信息
### Requirement: description字段必须支持中文字符
系统 SHALL 支持在 `description` 字段中使用中文字符和其他Unicode字符。
#### Scenario: metadata description包含中文
- **WHEN** metadata的description包含中文字符如 "这是关于项目的演示文稿"
- **THEN** 系统正确处理,不出现编码错误
#### Scenario: description包含中文
- **WHEN** 模板或幻灯片的description包含中文字符如 "这是中文描述"
- **THEN** 系统正确处理,不出现编码错误
#### Scenario: description包含多行文本
- **WHEN** description字段使用YAML多行文本格式
- **THEN** 系统正确读取完整的描述内容

View File

@@ -600,3 +600,161 @@ slides:
assert result["elements"][1].content == "Template2" assert result["elements"][1].content == "Template2"
assert result["elements"][2].content == "Custom1" assert result["elements"][2].content == "Custom1"
assert result["elements"][3].content == "Custom2" assert result["elements"][3].content == "Custom2"
# ============= Description 字段测试 =============
class TestPresentationDescription:
"""Presentation description 字段测试类"""
def test_metadata_with_description(self, temp_dir):
"""测试 metadata 包含 description 字段时正确加载"""
yaml_content = """
metadata:
title: "测试演示文稿"
description: "这是关于项目年度总结的演示文稿"
size: "16:9"
slides:
- elements: []
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
assert pres.description == "这是关于项目年度总结的演示文稿"
def test_metadata_without_description(self, temp_dir):
"""测试 metadata 不包含 description 字段时正常工作"""
yaml_content = """
metadata:
title: "测试演示文稿"
size: "16:9"
slides:
- elements: []
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
assert pres.description is None
def test_metadata_description_empty_string(self, temp_dir):
"""测试 metadata description 为空字符串时正常工作"""
yaml_content = """
metadata:
title: "测试演示文稿"
description: ""
size: "16:9"
slides:
- elements: []
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
assert pres.description == ""
def test_metadata_description_chinese_characters(self, temp_dir):
"""测试 metadata description 包含中文字符时正确处理"""
yaml_content = """
metadata:
title: "测试"
description: "这是关于项目的演示文稿,包含中文和特殊字符:测试、验证、确认"
size: "16:9"
slides:
- elements: []
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
assert "这是关于项目的演示文稿" in pres.description
assert "中文" in pres.description
class TestSlideDescription:
"""Slide description 字段测试类"""
def test_slide_with_description(self, sample_yaml):
"""测试幻灯片包含 description 字段时正确加载"""
pres = Presentation(str(sample_yaml))
slide_data = {
"description": "介绍项目背景和目标",
"elements": [
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
]
}
result = pres.render_slide(slide_data)
assert result["description"] == "介绍项目背景和目标"
def test_slide_without_description(self, sample_yaml):
"""测试幻灯片不包含 description 字段时正常工作"""
pres = Presentation(str(sample_yaml))
slide_data = {
"elements": [
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
]
}
result = pres.render_slide(slide_data)
assert result["description"] is None
def test_slide_description_empty_string(self, sample_yaml):
"""测试幻灯片 description 为空字符串时正常工作"""
pres = Presentation(str(sample_yaml))
slide_data = {
"description": "",
"elements": [
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
]
}
result = pres.render_slide(slide_data)
assert result["description"] == ""
def test_slide_description_chinese_characters(self, sample_yaml):
"""测试幻灯片 description 包含中文字符时正确处理"""
pres = Presentation(str(sample_yaml))
slide_data = {
"description": "这是幻灯片描述,包含中文内容",
"elements": [
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
]
}
result = pres.render_slide(slide_data)
assert "这是幻灯片描述" in result["description"]
assert "中文" in result["description"]
def test_slide_description_does_not_affect_rendering(self, sample_yaml):
"""测试 description 不影响渲染输出"""
pres = Presentation(str(sample_yaml))
slide_data = {
"description": "这段描述不应该影响渲染",
"elements": [
{"type": "text", "content": "Test Content", "box": [0, 0, 1, 1], "font": {}}
]
}
result = pres.render_slide(slide_data)
# description 字段存在但不影响元素渲染
assert result["description"] == "这段描述不应该影响渲染"
assert len(result["elements"]) == 1
assert result["elements"][0].content == "Test Content"

View File

@@ -8,6 +8,7 @@ import pytest
from pathlib import Path from pathlib import Path
from loaders.yaml_loader import YAMLError from loaders.yaml_loader import YAMLError
from core.template import Template from core.template import Template
from core.presentation import Presentation
# ============= 模板初始化测试 ============= # ============= 模板初始化测试 =============
@@ -892,3 +893,165 @@ slides:
slide_data = pres.data['slides'][0] slide_data = pres.data['slides'][0]
rendered = pres.render_slide(slide_data) rendered = pres.render_slide(slide_data)
assert len(rendered['elements']) == 1 assert len(rendered['elements']) == 1
# ============= Description 字段测试 =============
class TestTemplateDescription:
"""Template description 字段测试类"""
def test_template_with_description(self, temp_dir):
"""测试模板包含 description 字段时正确加载"""
template_content = """
description: "用于章节标题页的模板,包含主标题和副标题"
vars:
- name: title
required: true
- name: subtitle
required: false
default: ""
elements:
- type: text
content: "{title}"
box: [1, 1, 8, 1]
font:
size: 44
bold: true
- type: text
content: "{subtitle}"
box: [1, 2, 8, 1]
font:
size: 24
"""
template_path = temp_dir / "test-template.yaml"
template_path.write_text(template_content)
template = Template("test-template", templates_dir=temp_dir)
assert template.description == "用于章节标题页的模板,包含主标题和副标题"
def test_template_without_description(self, sample_template):
"""测试模板不包含 description 字段时正常工作"""
template = Template("title-slide", templates_dir=sample_template)
assert template.description is None
def test_template_description_empty_string(self, temp_dir):
"""测试模板 description 为空字符串时正常工作"""
template_content = """
description: ""
vars:
- name: title
elements:
- type: text
content: "{title}"
box: [1, 1, 8, 1]
font: {}
"""
template_path = temp_dir / "test-template.yaml"
template_path.write_text(template_content)
template = Template("test-template", templates_dir=temp_dir)
assert template.description == ""
def test_template_description_chinese_characters(self, temp_dir):
"""测试模板 description 包含中文字符时正确处理"""
template_content = """
description: "这是中文模板描述,用于标题页面"
vars:
- name: title
elements:
- type: text
content: "{title}"
box: [1, 1, 8, 1]
font: {}
"""
template_path = temp_dir / "test-template.yaml"
template_path.write_text(template_content)
template = Template("test-template", templates_dir=temp_dir)
assert "这是中文模板描述" in template.description
assert "标题页面" in template.description
def test_template_description_multiline(self, temp_dir):
"""测试模板 description 支持多行文本"""
template_content = """
description: |
这是一个多行描述。
第一行说明模板的用途。
第二行说明使用场景。
vars:
- name: title
elements:
- type: text
content: "{title}"
box: [1, 1, 8, 1]
font: {}
"""
template_path = temp_dir / "test-template.yaml"
template_path.write_text(template_content)
template = Template("test-template", templates_dir=temp_dir)
# 多行文本应该被正确读取
assert "这是一个多行描述" in template.description
assert "第一行说明模板的用途" in template.description
assert "第二行说明使用场景" in template.description
def test_inline_template_with_description(self, temp_dir):
"""测试内联模板包含 description 字段"""
yaml_content = """
metadata:
size: "16:9"
templates:
test-template:
description: "内联模板描述"
vars:
- name: title
elements:
- type: text
content: "{title}"
box: [1, 1, 8, 1]
font: {}
slides:
- template: test-template
vars:
title: "Test"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
template = pres.get_template("test-template")
assert template.description == "内联模板描述"
def test_template_description_does_not_affect_rendering(self, temp_dir):
"""测试 description 不影响模板渲染"""
template_content = """
description: "这段描述不应该影响渲染"
vars:
- name: title
elements:
- type: text
content: "{title}"
box: [1, 1, 8, 1]
font:
size: 44
"""
template_path = temp_dir / "test-template.yaml"
template_path.write_text(template_content)
template = Template("test-template", templates_dir=temp_dir)
# 渲染应该正常工作description 不影响结果
result = template.render({"title": "Test Title"})
assert len(result) == 1
assert result[0]["content"] == "Test Title"