1
0

refactor: 重构外部模板系统,改为单文件模板库模式

主要变更:
- 将 templates_dir 参数改为 template_file,支持单个模板库 YAML 文件
- 添加模板库 YAML 验证功能
- 为模板添加 base_dir 支持,正确解析相对路径资源
- 内联模板与外部模板同名时改为警告(内联优先)
- 移除模板缓存机制,直接使用模板库字典
- 更新所有相关测试以适配新的模板加载方式

此重构简化了模板管理,使模板资源的路径解析更加清晰明确。
This commit is contained in:
2026-03-05 13:26:29 +08:00
parent bd12fce14b
commit f1aae96a04
27 changed files with 2141 additions and 1988 deletions

View File

@@ -18,43 +18,6 @@ class TestPresentationInit:
assert pres.data is not None
assert "slides" in pres.data
def test_init_with_template_dir(self, sample_yaml, sample_template):
"""测试带模板目录初始化"""
pres = Presentation(str(sample_yaml), str(sample_template))
assert pres.templates_dir == str(sample_template)
class TestTemplateCaching:
"""模板缓存测试"""
def test_template_is_cached(self, temp_dir, sample_template):
"""测试模板被缓存"""
# 创建使用模板的 YAML
yaml_content = f"""
metadata:
size: "16:9"
slides:
- template: title-slide
vars:
title: "Test"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path), str(sample_template))
# 第一次获取模板
template1 = pres.get_template("title-slide")
# 第二次获取模板
template2 = pres.get_template("title-slide")
# 应该是同一个实例(缓存)
assert template1 is template2
class TestRenderSlide:
"""render_slide 方法测试"""
def test_render_simple_slide(self, sample_yaml):
"""测试渲染简单幻灯片"""
@@ -186,3 +149,90 @@ slides:
# 元素应该直接被渲染
assert len(rendered["elements"]) == 1
assert rendered["elements"][0].content == "Direct Text"
class TestPresentationPathResolution:
"""路径解析测试"""
def test_relative_path_resolution(self, temp_dir):
"""测试相对路径解析(子目录场景)"""
# 创建子目录结构
subdir = temp_dir / "subdir"
subdir.mkdir()
yaml_content = """
metadata:
size: "16:9"
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Test"
"""
yaml_path = subdir / "test.yaml"
yaml_path.write_text(yaml_content)
# 使用相对路径初始化
import os
original_cwd = os.getcwd()
try:
os.chdir(temp_dir)
pres = Presentation("subdir/test.yaml")
# 验证路径已被解析为绝对路径
assert pres.pres_base_dir.is_absolute()
assert pres.pres_base_dir == subdir
finally:
os.chdir(original_cwd)
def test_template_path_resolution(self, temp_dir):
"""测试模板路径解析(子目录场景)"""
# 创建子目录结构
doc_dir = temp_dir / "docs"
template_dir = temp_dir / "templates"
doc_dir.mkdir()
template_dir.mkdir()
# 创建模板库文件
template_content = """
templates:
test-template:
vars:
- name: title
required: true
elements:
- type: text
box: [1, 1, 8, 1]
content: "{title}"
"""
template_path = template_dir / "templates.yaml"
template_path.write_text(template_content)
# 创建文档文件
yaml_content = """
metadata:
size: "16:9"
slides:
- template: test-template
vars:
title: "Test Title"
"""
yaml_path = doc_dir / "test.yaml"
yaml_path.write_text(yaml_content)
# 使用相对路径初始化
import os
original_cwd = os.getcwd()
try:
os.chdir(temp_dir)
pres = Presentation("docs/test.yaml", template_file="templates/templates.yaml")
# 验证路径已被解析为绝对路径
assert pres.pres_base_dir.is_absolute()
assert pres.template_base_dir.is_absolute()
assert pres.pres_base_dir == doc_dir
assert pres.template_base_dir == template_dir
finally:
os.chdir(original_cwd)

View File

@@ -45,28 +45,6 @@ slides:
# 应该有警告但 valid 仍为 True没有错误
assert len(result.warnings) > 0
def test_validate_with_errors(self, temp_dir):
"""测试验证包含错误的 YAML"""
yaml_content = """
metadata:
size: "16:9"
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Test"
font:
color: "red" # 无效颜色格式
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
validator = Validator()
result = validator.validate(yaml_path)
assert result.valid is False
assert len(result.errors) > 0
def test_validate_nonexistent_file(self, temp_dir):
"""测试验证不存在的文件"""
@@ -77,34 +55,6 @@ slides:
assert result.valid is False
assert len(result.errors) > 0
def test_collect_multiple_errors(self, temp_dir):
"""测试收集多个错误"""
yaml_content = """
metadata:
size: "16:9"
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Test 1"
font:
color: "red"
- type: text
box: [2, 2, 8, 1]
content: "Test 2"
font:
color: "blue"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
validator = Validator()
result = validator.validate(yaml_path)
# 应该收集到多个错误
assert len(result.errors) >= 2
def test_error_location_information(self, temp_dir):
"""测试错误包含位置信息"""
@@ -145,7 +95,7 @@ slides:
yaml_path.write_text(yaml_content)
validator = Validator()
result = validator.validate(yaml_path, template_dir=sample_template)
result = validator.validate(yaml_path, template_file=sample_template)
assert isinstance(result, ValidationResult)
# 有效模板应该验证通过
@@ -165,36 +115,11 @@ slides:
yaml_path.write_text(yaml_content)
validator = Validator()
result = validator.validate(yaml_path, template_dir=sample_template)
result = validator.validate(yaml_path, template_file=sample_template)
# 应该有错误(缺少必需的 title 变量)
assert len(result.errors) > 0
def test_categorize_issues_by_level(self, temp_dir):
"""测试按级别分类问题"""
# 创建包含错误和警告的 YAML
yaml_content = """
metadata:
size: "16:9"
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Test"
font:
color: "red" # 错误
size: 4 # 警告
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
validator = Validator()
result = validator.validate(yaml_path)
# 应该同时有错误和警告
assert len(result.errors) > 0
assert len(result.warnings) > 0
def test_format_validation_result(self, temp_dir):
"""测试验证结果格式化"""