feat: add YAML validation with check command and auto-validation
Implements comprehensive validation before PPTX conversion to catch errors early. Includes element-level validation (colors, fonts, table consistency) and system-level validation (geometry, resources). Supports standalone check command and automatic validation during conversion.
This commit is contained in:
139
README_DEV.md
139
README_DEV.md
@@ -12,14 +12,20 @@ yaml2pptx 是一个将 YAML 格式的演示文稿源文件转换为 PPTX 文件
|
||||
|
||||
```
|
||||
html2pptx/
|
||||
├── yaml2pptx.py (127 行) # 入口脚本,CLI + main 函数
|
||||
├── yaml2pptx.py (200 行) # 入口脚本,CLI + main 函数
|
||||
├── utils.py (74 行) # 工具函数(日志、颜色转换)
|
||||
├── core/ # 核心领域模型
|
||||
│ ├── elements.py (96 行) # 元素抽象层(dataclass)
|
||||
│ ├── elements.py (200 行) # 元素抽象层(dataclass + validate)
|
||||
│ ├── template.py (191 行) # 模板系统
|
||||
│ └── presentation.py (91 行) # 演示文稿类
|
||||
├── loaders/ # 数据加载层
|
||||
│ └── yaml_loader.py (113 行) # YAML 加载和验证
|
||||
├── validators/ # 验证层
|
||||
│ ├── __init__.py # 导出主验证器
|
||||
│ ├── result.py (70 行) # 验证结果数据结构
|
||||
│ ├── validator.py (150 行) # 主验证器
|
||||
│ ├── geometry.py (120 行) # 几何验证器
|
||||
│ └── resource.py (110 行) # 资源验证器
|
||||
├── renderers/ # 渲染层
|
||||
│ ├── pptx_renderer.py (292 行) # PPTX 渲染器
|
||||
│ └── html_renderer.py (172 行) # HTML 渲染器(预览)
|
||||
@@ -34,6 +40,12 @@ yaml2pptx.py (入口)
|
||||
↓
|
||||
├─→ utils (工具函数)
|
||||
├─→ loaders.yaml_loader (YAML 加载)
|
||||
├─→ validators.validator (验证器)
|
||||
│ ↓
|
||||
│ ├─→ validators.result (验证结果)
|
||||
│ ├─→ validators.geometry (几何验证)
|
||||
│ ├─→ validators.resource (资源验证)
|
||||
│ └─→ core.elements (元素验证)
|
||||
├─→ core.presentation (演示文稿)
|
||||
│ ↓
|
||||
│ ├─→ core.template (模板)
|
||||
@@ -49,9 +61,10 @@ yaml2pptx.py (入口)
|
||||
```
|
||||
|
||||
**依赖原则**:
|
||||
- 单向依赖:入口 → 渲染 → 核心 ← 加载
|
||||
- 单向依赖:入口 → 验证/渲染 → 核心 ← 加载
|
||||
- 无循环依赖
|
||||
- 核心层不依赖其他业务模块
|
||||
- 验证层可以调用核心层的元素验证方法
|
||||
|
||||
## 模块职责
|
||||
|
||||
@@ -81,15 +94,37 @@ yaml2pptx.py (入口)
|
||||
### 4. core/elements.py(核心层 - 元素抽象)
|
||||
- **职责**:定义元素数据类和工厂函数
|
||||
- **包含**:
|
||||
- `TextElement` - 文本元素(dataclass)
|
||||
- `ImageElement` - 图片元素(dataclass)
|
||||
- `ShapeElement` - 形状元素(dataclass)
|
||||
- `TableElement` - 表格元素(dataclass)
|
||||
- `_is_valid_color()` - 颜色格式验证工具函数
|
||||
- `TextElement` - 文本元素(dataclass + validate)
|
||||
- `ImageElement` - 图片元素(dataclass + validate)
|
||||
- `ShapeElement` - 形状元素(dataclass + validate)
|
||||
- `TableElement` - 表格元素(dataclass + validate)
|
||||
- `create_element()` - 元素工厂函数
|
||||
- **特点**:
|
||||
- 使用 `@dataclass` 装饰器
|
||||
- 在 `__post_init__` 中进行验证
|
||||
- 创建时验证,尽早发现错误
|
||||
- 在 `__post_init__` 中进行创建时验证
|
||||
- 在 `validate()` 方法中进行元素级验证
|
||||
- 元素类负责自身属性的验证(颜色格式、字体大小、枚举值等)
|
||||
|
||||
### 4.5. validators/(验证层)
|
||||
- **职责**:YAML 文件验证,在转换前检查问题
|
||||
- **包含**:
|
||||
- `validators/result.py` - 验证结果数据结构
|
||||
- `ValidationIssue` - 验证问题(level, message, location, code)
|
||||
- `ValidationResult` - 验证结果(errors, warnings, infos)
|
||||
- `validators/geometry.py` - 几何验证器
|
||||
- `GeometryValidator` - 检查元素边界、页面范围
|
||||
- 支持 0.1 英寸容忍度
|
||||
- `validators/resource.py` - 资源验证器
|
||||
- `ResourceValidator` - 检查图片、模板文件存在性
|
||||
- 验证模板文件结构
|
||||
- `validators/validator.py` - 主验证器
|
||||
- `Validator` - 协调所有子验证器
|
||||
- 集成元素级验证、几何验证、资源验证
|
||||
- **特点**:
|
||||
- 分级错误报告(ERROR/WARNING/INFO)
|
||||
- ERROR 阻止转换,WARNING 不阻止
|
||||
- 验证职责分层:元素级验证在元素类中,系统级验证在验证器中
|
||||
|
||||
### 5. core/template.py(核心层 - 模板)
|
||||
- **职责**:模板加载和变量解析
|
||||
@@ -256,6 +291,72 @@ class PptxGenerator:
|
||||
- 类型安全:进行类型检查
|
||||
- 易于扩展:添加新元素类型只需添加一个分支
|
||||
|
||||
### 5. 验证职责分层
|
||||
|
||||
**决策**:将验证逻辑分为两层
|
||||
1. **元素级验证**:放在元素类本身(`core/elements.py`)
|
||||
2. **系统级验证**:放在独立的验证器模块(`validators/`)
|
||||
|
||||
**理由**:
|
||||
- 元素类最了解自己的约束,应该负责自身的完整性验证
|
||||
- 系统级验证需要全局上下文(如页面尺寸、文件路径),适合集中处理
|
||||
- 符合单一职责原则,便于扩展和维护
|
||||
|
||||
**元素级验证职责**:
|
||||
- 必需字段检查(在 `__post_init__` 中)
|
||||
- 数据类型检查(在 `__post_init__` 中)
|
||||
- 值的有效性检查(在 `validate()` 方法中)
|
||||
- 颜色格式验证
|
||||
- 字体大小合理性
|
||||
- 枚举值检查(如形状类型)
|
||||
- 表格数据一致性
|
||||
|
||||
**系统级验证职责**:
|
||||
- 几何验证(元素是否在页面范围内,需要知道页面尺寸)
|
||||
- 资源验证(文件是否存在,需要知道文件路径)
|
||||
- 跨元素验证(如果未来需要)
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
# 元素级验证(在元素类中)
|
||||
@dataclass
|
||||
class TextElement:
|
||||
def validate(self) -> List[ValidationIssue]:
|
||||
issues = []
|
||||
if self.font.get('color'):
|
||||
if not _is_valid_color(self.font['color']):
|
||||
issues.append(ValidationIssue(
|
||||
level="ERROR",
|
||||
message=f"无效的颜色格式: {self.font['color']}",
|
||||
code="INVALID_COLOR_FORMAT"
|
||||
))
|
||||
return issues
|
||||
|
||||
# 系统级验证(在验证器中)
|
||||
class GeometryValidator:
|
||||
def validate_element(self, element, slide_index, elem_index):
|
||||
# 需要页面尺寸信息
|
||||
if element.box[0] + element.box[2] > self.slide_width:
|
||||
# 报告边界超出
|
||||
```
|
||||
|
||||
### 6. 验证容忍度
|
||||
|
||||
**决策**:几何验证时,允许 0.1 英寸的容忍度
|
||||
|
||||
**理由**:
|
||||
- 浮点数计算可能有精度误差
|
||||
- 0.1 英寸(约 2.54mm)在视觉上几乎不可见
|
||||
- 避免误报,提升用户体验
|
||||
|
||||
**实现**:
|
||||
```python
|
||||
TOLERANCE = 0.1 # 英寸
|
||||
|
||||
if right > slide_width + TOLERANCE:
|
||||
# 报告 WARNING
|
||||
```
|
||||
|
||||
## 扩展指南
|
||||
|
||||
### 添加新元素类型
|
||||
@@ -351,17 +452,29 @@ def main():
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
# 基本 PPTX 生成
|
||||
# 验证 YAML 文件
|
||||
uv run yaml2pptx.py check temp/test.yaml
|
||||
|
||||
# 使用模板时验证
|
||||
uv run yaml2pptx.py check temp/demo.yaml --template-dir temp/templates
|
||||
|
||||
# 使用 convert 子命令转换(推荐)
|
||||
uv run yaml2pptx.py convert temp/test.yaml temp/output.pptx
|
||||
|
||||
# 传统模式转换(向后兼容)
|
||||
uv run yaml2pptx.py temp/test.yaml temp/output.pptx
|
||||
|
||||
# 跳过自动验证
|
||||
uv run yaml2pptx.py convert temp/test.yaml temp/output.pptx --no-check
|
||||
|
||||
# 使用模板
|
||||
uv run yaml2pptx.py temp/demo.yaml temp/output.pptx --template-dir temp/templates
|
||||
uv run yaml2pptx.py convert temp/demo.yaml temp/output.pptx --template-dir temp/templates
|
||||
|
||||
# 预览模式
|
||||
uv run yaml2pptx.py temp/test.yaml --preview
|
||||
uv run yaml2pptx.py convert temp/test.yaml --preview
|
||||
|
||||
# 指定端口
|
||||
uv run yaml2pptx.py temp/test.yaml --preview --port 8080
|
||||
uv run yaml2pptx.py convert temp/test.yaml --preview --port 8080
|
||||
```
|
||||
|
||||
### 测试文件位置
|
||||
|
||||
Reference in New Issue
Block a user