refactor: modularize yaml2pptx into layered architecture
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)
This commit is contained in:
91
core/presentation.py
Normal file
91
core/presentation.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""
|
||||
演示文稿模块
|
||||
|
||||
管理整个演示文稿的生成流程。
|
||||
"""
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user