feat: update auto render

This commit is contained in:
2025-08-07 20:03:53 +08:00
parent fd67864247
commit d7e8ca38f8
39 changed files with 5684 additions and 130 deletions

View 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,
}
}