# 扩展指南 本文档说明如何扩展 yaml2pptx 的功能。 ## 添加新元素类型 假设要添加 `VideoElement`: ### 1. 在 core/elements.py 中定义数据类 ```python from dataclasses import dataclass, field @dataclass class VideoElement: type: str = 'video' src: str = '' box: list = field(default_factory=lambda: [1, 1, 4, 3]) autoplay: bool = False def __post_init__(self): if not self.src: raise ValueError("视频元素必须指定 src") if len(self.box) != 4: raise ValueError("box 必须包含 4 个数字") ``` ### 2. 在工厂函数中添加分支 ```python def create_element(elem_dict: dict): elem_type = elem_dict.get('type') if elem_type == 'text': return TextElement(**elem_dict) elif elem_type == 'image': return ImageElement(**elem_dict) # ... 其他类型 ... elif elem_type == 'video': return VideoElement(**elem_dict) else: raise ValueError(f"Unknown element type: {elem_type}") ``` ### 3. 在 PptxGenerator 中实现渲染方法 ```python def _render_element(self, slide, elem, base_path): # ... 其他类型 ... elif isinstance(elem, VideoElement): self._render_video(slide, elem, base_path) def _render_video(self, slide, elem: VideoElement, base_path): """实现视频渲染逻辑""" movie = slide.shapes.add_movie( str(Path(base_path) / elem.src), left=Inches(elem.box[0]), top=Inches(elem.box[1]), width=Inches(elem.box[2]), height=Inches(elem.box[3]) ) if elem.autoplay: movie.click.action = pp.action.Action(pyppote.xmlns.namespace('p').MSO_ANIMATION_VIDEO_CLICK) ``` ### 4. 在 HtmlRenderer 中实现渲染方法 ```python def render_slide(self, slide_data, index, base_path=None): elements_html = "" for elem in slide_data: # ... 其他类型 ... elif isinstance(elem, VideoElement): elements_html += self.render_video(elem, base_path) return self.SLIDE_TEMPLATE.format(content=elements_html) def render_video(self, elem: VideoElement, base_path): """实现 HTML 视频渲染""" src_path = str(Path(base_path) / elem.src) if base_path else elem.src autoplay_attr = "autoplay" if elem.autoplay else "" return f''' ''' ``` ### 5. 更新验证器 如果需要验证视频文件: ```python # validators/resource.py def validate_video(self, src, slide_index, elem_index): """检查视频文件是否存在""" video_path = self.base_dir / src if not video_path.exists(): return ValidationIssue( level="ERROR", message=f"视频文件不存在: {src}", location=f"[幻灯片 {slide_index + 1}, 元素 {elem_index + 1}]", code="VIDEO_FILE_NOT_FOUND" ) return None ``` ## 添加新渲染器 假设要添加 PDF 渲染器: ### 1. 创建 renderers/pdf_renderer.py ```python from core.elements import TextElement, ImageElement, ShapeElement, TableElement class PdfRenderer: def __init__(self, size="16:9"): # 初始化 PDF 库 self.size = size # ... def add_slide(self, slide_data, base_path=None): """添加页面""" # 实现... pass def _render_element(self, page, elem, base_path): """渲染元素到 PDF 页面""" if isinstance(elem, TextElement): self._render_text(page, elem) elif isinstance(elem, ImageElement): self._render_image(page, elem, base_path) elif isinstance(elem, ShapeElement): self._render_shape(page, elem) elif isinstance(elem, TableElement): self._render_table(page, elem) def _render_text(self, page, elem): """渲染文本到 PDF""" # 实现... pass def _render_image(self, page, elem, base_path): """渲染图片到 PDF""" # 实现... pass def _render_shape(self, page, elem): """渲染形状到 PDF""" # 实现... pass def _render_table(self, page, elem): """渲染表格到 PDF""" # 实现... pass def save(self, output_path): """保存 PDF 文件""" # 实现... pass ``` ### 2. 在 yaml2pptx.py 中添加 PDF 模式 ```python from renderers.pdf_renderer import PdfRenderer def main(): # ... 解析参数 ... if args.pdf: # PDF 生成模式 generator = PdfRenderer(size=args.size) # ... 渲染逻辑 ``` ### 3. 添加命令行参数 ```python def parse_args(): parser = argparse.ArgumentParser(description='YAML to PPTX converter') subparsers = parser.add_subparsers(dest='command', help='子命令') # ... 其他命令 ... # PDF 命令 pdf_parser = subparsers.add_parser('pdf', help='生成 PDF') pdf_parser.add_argument('input', help='输入的 YAML 文件') pdf_parser.add_argument('output', help='输出的 PDF 文件', nargs='?') pdf_parser.add_argument('--template', help='模板库文件路径') pdf_parser.add_argument('--size', default='16:9', choices=['16:9', '4:3']) return parser.parse_args() ``` ## 添加新的验证规则 ### 1. 在 validators/ 中创建新的验证器 ```python # validators/custom.py class CustomValidator: def __init__(self): pass def validate(self, presentation): """执行自定义验证""" issues = [] # 验证逻辑 return issues ``` ### 2. 在主验证器中集成 ```python # validators/validator.py class Validator: def __init__(self, ...): # ... self.custom_validator = CustomValidator() def validate_presentation(self, presentation): # ... # 调用自定义验证器 custom_issues = self.custom_validator.validate(presentation) result.infos.extend(custom_issues) ``` ## 测试新功能 ### 1. 创建测试文件 ```python # tests/unit/test_video_element.py import pytest from core.elements import VideoElement, create_element def test_create_video_element(): elem_dict = { 'type': 'video', 'src': 'test.mp4', 'box': [1, 1, 4, 3], 'autoplay': True } elem = create_element(elem_dict) assert isinstance(elem, VideoElement) assert elem.autoplay is True def test_video_element_without_src(): with pytest.raises(ValueError, match="必须指定 src"): VideoElement(src='', box=[1, 1, 4, 3]) ``` ### 2. 运行测试 ```bash uv run pytest tests/unit/test_video_element.py -v ``` ## 提交变更 1. 更新相关文档 2. 添加测试 3. 运行完整测试套件 4. 提交 Pull Request ## 相关文档 - [架构设计](architecture.md) - 代码结构 - [Elements 模块](modules/elements.md) - 元素抽象层 [返回开发文档索引](../README.md)