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:
131
validators/geometry.py
Normal file
131
validators/geometry.py
Normal file
@@ -0,0 +1,131 @@
|
||||
"""
|
||||
几何验证器
|
||||
|
||||
验证元素的位置和尺寸是否在页面范围内。
|
||||
"""
|
||||
|
||||
from validators.result import ValidationIssue
|
||||
|
||||
|
||||
# 容忍度:0.1 英寸
|
||||
TOLERANCE = 0.1
|
||||
|
||||
|
||||
class GeometryValidator:
|
||||
"""几何验证器"""
|
||||
|
||||
def __init__(self, slide_width: float, slide_height: float):
|
||||
"""
|
||||
初始化几何验证器
|
||||
|
||||
Args:
|
||||
slide_width: 幻灯片宽度(英寸)
|
||||
slide_height: 幻灯片高度(英寸)
|
||||
"""
|
||||
self.slide_width = slide_width
|
||||
self.slide_height = slide_height
|
||||
|
||||
def validate_element(self, element, slide_index: int, elem_index: int) -> list:
|
||||
"""
|
||||
验证元素的几何属性
|
||||
|
||||
Args:
|
||||
element: 元素对象
|
||||
slide_index: 幻灯片索引(从 1 开始)
|
||||
elem_index: 元素索引(从 1 开始)
|
||||
|
||||
Returns:
|
||||
验证问题列表
|
||||
"""
|
||||
issues = []
|
||||
location = f"幻灯片 {slide_index}, 元素 {elem_index}"
|
||||
|
||||
# 检查元素边界
|
||||
if hasattr(element, 'box'):
|
||||
issues.extend(self._check_element_bounds(
|
||||
element.box, location
|
||||
))
|
||||
|
||||
# 检查表格边界
|
||||
if hasattr(element, 'position') and hasattr(element, 'col_widths'):
|
||||
if element.col_widths:
|
||||
issues.extend(self._check_table_bounds(
|
||||
element.position, element.col_widths, location
|
||||
))
|
||||
|
||||
return issues
|
||||
|
||||
def _check_element_bounds(self, box: list, location: str) -> list:
|
||||
"""
|
||||
检查元素边界是否在页面范围内
|
||||
|
||||
Args:
|
||||
box: [left, top, width, height]
|
||||
location: 位置信息
|
||||
|
||||
Returns:
|
||||
验证问题列表
|
||||
"""
|
||||
issues = []
|
||||
left, top, width, height = box
|
||||
right = left + width
|
||||
bottom = top + height
|
||||
|
||||
# 检查元素是否完全在页面外
|
||||
if (right <= 0 or bottom <= 0 or
|
||||
left >= self.slide_width or top >= self.slide_height):
|
||||
issues.append(ValidationIssue(
|
||||
level="WARNING",
|
||||
message="元素完全在页面外",
|
||||
location=location,
|
||||
code="ELEMENT_COMPLETELY_OUT_OF_BOUNDS"
|
||||
))
|
||||
return issues
|
||||
|
||||
# 检查右边界
|
||||
if right > self.slide_width + TOLERANCE:
|
||||
issues.append(ValidationIssue(
|
||||
level="WARNING",
|
||||
message=f"元素右边界超出: {right:.2f} > {self.slide_width}",
|
||||
location=location,
|
||||
code="ELEMENT_OUT_OF_BOUNDS"
|
||||
))
|
||||
|
||||
# 检查下边界
|
||||
if bottom > self.slide_height + TOLERANCE:
|
||||
issues.append(ValidationIssue(
|
||||
level="WARNING",
|
||||
message=f"元素下边界超出: {bottom:.2f} > {self.slide_height}",
|
||||
location=location,
|
||||
code="ELEMENT_OUT_OF_BOUNDS"
|
||||
))
|
||||
|
||||
return issues
|
||||
|
||||
def _check_table_bounds(self, position: list, col_widths: list, location: str) -> list:
|
||||
"""
|
||||
检查表格边界是否在页面范围内
|
||||
|
||||
Args:
|
||||
position: [left, top]
|
||||
col_widths: 列宽列表
|
||||
location: 位置信息
|
||||
|
||||
Returns:
|
||||
验证问题列表
|
||||
"""
|
||||
issues = []
|
||||
left, top = position
|
||||
table_width = sum(col_widths)
|
||||
right = left + table_width
|
||||
|
||||
# 检查表格右边界
|
||||
if right > self.slide_width + TOLERANCE:
|
||||
issues.append(ValidationIssue(
|
||||
level="WARNING",
|
||||
message=f"表格超出页面宽度: {right:.2f} > {self.slide_width}",
|
||||
location=location,
|
||||
code="TABLE_OUT_OF_BOUNDS"
|
||||
))
|
||||
|
||||
return issues
|
||||
Reference in New Issue
Block a user