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)
92 lines
2.6 KiB
Python
92 lines
2.6 KiB
Python
"""
|
|
演示文稿模块
|
|
|
|
管理整个演示文稿的生成流程。
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from loaders.yaml_loader import load_yaml_file, validate_presentation_yaml
|
|
from core.template import Template
|
|
from core.elements import create_element
|
|
|
|
|
|
class Presentation:
|
|
"""演示文稿类,管理整个演示文稿的生成流程"""
|
|
|
|
def __init__(self, pres_file, templates_dir=None):
|
|
"""
|
|
初始化演示文稿
|
|
|
|
Args:
|
|
pres_file: 演示文稿 YAML 文件路径
|
|
templates_dir: 模板目录
|
|
"""
|
|
self.pres_file = Path(pres_file)
|
|
self.templates_dir = templates_dir
|
|
|
|
# 加载演示文稿文件
|
|
self.data = load_yaml_file(pres_file)
|
|
validate_presentation_yaml(self.data, str(pres_file))
|
|
|
|
# 获取演示文稿尺寸
|
|
metadata = self.data.get('metadata', {})
|
|
self.size = metadata.get('size', '16:9')
|
|
|
|
# 模板缓存
|
|
self.template_cache = {}
|
|
|
|
def get_template(self, template_name):
|
|
"""
|
|
获取模板(带缓存)
|
|
|
|
Args:
|
|
template_name: 模板名称
|
|
|
|
Returns:
|
|
Template 对象
|
|
"""
|
|
if template_name not in self.template_cache:
|
|
self.template_cache[template_name] = Template(
|
|
template_name, self.templates_dir
|
|
)
|
|
return self.template_cache[template_name]
|
|
|
|
def render_slide(self, slide_data):
|
|
"""
|
|
渲染单个幻灯片
|
|
|
|
Args:
|
|
slide_data: 幻灯片数据字典
|
|
|
|
Returns:
|
|
dict: 包含 background 和 elements 的字典
|
|
"""
|
|
if 'template' in slide_data:
|
|
# 使用模板
|
|
template_name = slide_data['template']
|
|
template = self.get_template(template_name)
|
|
vars_values = slide_data.get('vars', {})
|
|
elements = template.render(vars_values)
|
|
|
|
# 合并背景(如果有)
|
|
background = slide_data.get('background', None)
|
|
|
|
# 将元素字典转换为元素对象
|
|
element_objects = [create_element(elem) for elem in elements]
|
|
|
|
return {
|
|
'background': background,
|
|
'elements': element_objects
|
|
}
|
|
else:
|
|
# 自定义幻灯片
|
|
elements = slide_data.get('elements', [])
|
|
|
|
# 将元素字典转换为元素对象
|
|
element_objects = [create_element(elem) for elem in elements]
|
|
|
|
return {
|
|
'background': slide_data.get('background'),
|
|
'elements': element_objects
|
|
}
|