feat: update auto render
This commit is contained in:
181
internal/template/validator.go
Normal file
181
internal/template/validator.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type TemplateValidator struct {
|
||||
config TemplateConfig
|
||||
}
|
||||
|
||||
type ValidationResult struct {
|
||||
Valid bool `json:"valid"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
Template string `json:"template"`
|
||||
Table string `json:"table"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
func NewTemplateValidator(config TemplateConfig) *TemplateValidator {
|
||||
return &TemplateValidator{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (tv *TemplateValidator) ValidateTemplate(templateType, tableName string) ValidationResult {
|
||||
result := ValidationResult{
|
||||
Valid: true,
|
||||
Template: templateType,
|
||||
Table: tableName,
|
||||
Type: templateType,
|
||||
}
|
||||
|
||||
// 验证模板文件存在性
|
||||
paths := tv.getTemplatePaths(templateType, tableName)
|
||||
found := false
|
||||
|
||||
for _, path := range paths {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
result.Valid = false
|
||||
result.Errors = append(result.Errors, fmt.Sprintf("未找到模板文件: %s", templateType))
|
||||
return result
|
||||
}
|
||||
|
||||
// 验证模板语法
|
||||
loader := NewTemplateLoader(tv.config)
|
||||
_, err := loader.LoadTemplate(templateType, tableName)
|
||||
if err != nil {
|
||||
result.Valid = false
|
||||
result.Errors = append(result.Errors, fmt.Sprintf("模板语法错误: %v", err))
|
||||
}
|
||||
|
||||
// 验证模板结构
|
||||
tv.validateTemplateStructure(&result, templateType, tableName)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (tv *TemplateValidator) ValidateAllTemplates() []ValidationResult {
|
||||
var results []ValidationResult
|
||||
|
||||
// 验证所有内置模板
|
||||
builtinTemplates := []string{"list", "card", "timeline"}
|
||||
for _, templateType := range builtinTemplates {
|
||||
result := tv.ValidateTemplate(templateType, "_default")
|
||||
results = append(results, result)
|
||||
}
|
||||
|
||||
// 验证自定义目录下的模板
|
||||
if entries, err := os.ReadDir(tv.config.CustomPath); err == nil {
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() && entry.Name() != "_default" {
|
||||
tableName := entry.Name()
|
||||
for _, templateType := range builtinTemplates {
|
||||
result := tv.ValidateTemplate(templateType, tableName)
|
||||
results = append(results, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func (tv *TemplateValidator) getTemplatePaths(templateType, tableName string) []string {
|
||||
return []string{
|
||||
// 自定义模板
|
||||
filepath.Join(tv.config.CustomPath, tableName, fmt.Sprintf("%s.html", templateType)),
|
||||
// 默认自定义模板
|
||||
filepath.Join(tv.config.CustomPath, "_default", fmt.Sprintf("%s.html", templateType)),
|
||||
// 内置模板
|
||||
filepath.Join(tv.config.BuiltinPath, fmt.Sprintf("%s.html", templateType)),
|
||||
}
|
||||
}
|
||||
|
||||
func (tv *TemplateValidator) validateTemplateStructure(result *ValidationResult, templateType, tableName string) {
|
||||
// 验证必需的文件结构
|
||||
requiredFiles := []string{
|
||||
"layout.html",
|
||||
}
|
||||
|
||||
for _, file := range requiredFiles {
|
||||
path := filepath.Join(tv.config.BuiltinPath, file)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
result.Valid = false
|
||||
result.Errors = append(result.Errors, fmt.Sprintf("缺少必需文件: %s", file))
|
||||
}
|
||||
}
|
||||
|
||||
// 验证字段模板
|
||||
fieldPath := filepath.Join(tv.config.BuiltinPath, "field")
|
||||
if _, err := os.Stat(fieldPath); err == nil {
|
||||
requiredFieldTemplates := []string{"raw.html", "time.html", "tag.html", "markdown.html", "category.html"}
|
||||
|
||||
for _, fieldTpl := range requiredFieldTemplates {
|
||||
fieldPath := filepath.Join(fieldPath, fieldTpl)
|
||||
if _, err := os.Stat(fieldPath); err != nil {
|
||||
result.Warnings = append(result.Warnings, fmt.Sprintf("缺少字段模板: %s", fieldTpl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 验证自定义模板目录结构
|
||||
if tableName != "_default" {
|
||||
customTablePath := filepath.Join(tv.config.CustomPath, tableName)
|
||||
if _, err := os.Stat(customTablePath); err == nil {
|
||||
// 检查是否有list或card模板
|
||||
hasList := false
|
||||
hasCard := false
|
||||
|
||||
if _, err := os.Stat(filepath.Join(customTablePath, "list.html")); err == nil {
|
||||
hasList = true
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(customTablePath, "card.html")); err == nil {
|
||||
hasCard = true
|
||||
}
|
||||
|
||||
if !hasList && !hasCard {
|
||||
result.Warnings = append(result.Warnings, "自定义模板目录存在但缺少list.html或card.html")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模板健康检查
|
||||
func (tv *TemplateValidator) HealthCheck() map[string]interface{} {
|
||||
results := tv.ValidateAllTemplates()
|
||||
|
||||
total := len(results)
|
||||
valid := 0
|
||||
errors := 0
|
||||
warnings := 0
|
||||
|
||||
for _, result := range results {
|
||||
if result.Valid {
|
||||
valid++
|
||||
}
|
||||
if len(result.Errors) > 0 {
|
||||
errors += len(result.Errors)
|
||||
}
|
||||
if len(result.Warnings) > 0 {
|
||||
warnings += len(result.Warnings)
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"total": total,
|
||||
"valid": valid,
|
||||
"errors": errors,
|
||||
"warnings": warnings,
|
||||
"details": results,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user