""" 演示文稿模块 管理整个演示文稿的生成流程。 """ from pathlib import Path from loaders.yaml_loader import load_yaml_file, validate_presentation_yaml, YAMLError 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") # 验证尺寸值 if not isinstance(self.size, str): raise ValueError( f"无效的尺寸值: {self.size},尺寸必须是字符串(如 '16:9' 或 '4:3')" ) # 模板缓存 self.template_cache = {} # 解析并保存内联模板 self.inline_templates = self.data.get('templates', {}) def get_template(self, template_name): """ 获取模板(优先检查内联模板,检测同名冲突) Args: template_name: 模板名称 Returns: Template 对象 Raises: YAMLError: 内联和外部模板同名 """ # 1. 先检查内联模板 if template_name in self.inline_templates: # 2. 检查外部模板是否也存在同名 if self._external_template_exists(template_name): raise YAMLError( f"模板名称冲突: '{template_name}' 同时存在于内联模板和外部模板目录\n" f"请使用不同的模板名称以避免冲突" ) inline_data = self.inline_templates[template_name] return Template.from_data(inline_data, template_name) # 3. 回退到外部模板 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 _external_template_exists(self, template_name): """检查外部模板文件是否存在""" if not self.templates_dir: return False template_path = Path(self.templates_dir) / f"{template_name}.yaml" return template_path.exists() 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, }