181 lines
4.7 KiB
Go
181 lines
4.7 KiB
Go
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,
|
|
}
|
|
} |