package operation import ( "fmt" goHtmlTemplate "html/template" "log" "mime" "path/filepath" "strings" "github.com/aziis98/cabret" "github.com/aziis98/cabret/operation/template" "github.com/aziis98/cabret/util" ) var HtmlMimeType = mime.TypeByExtension(".html") func init() { registerType("layout", &Layout{}) } type Layout struct { // TemplatePatterns is a list of glob patterns of templates that will be loaded TemplatePatterns []string } func (op *Layout) Load(config map[string]any) error { if v, ok := config[ShortFormValueKey]; ok { globPatternsStr, ok := v.(string) if !ok { return fmt.Errorf(`expected a comma separated list of glob patterns but got "%v" of type %T`, v, v) } globPatterns := strings.Split(globPatternsStr, ",") for _, pat := range globPatterns { op.TemplatePatterns = append(op.TemplatePatterns, strings.TrimSpace(pat)) } return nil } if v, ok := config["paths"]; ok { globPatterns, ok := v.([]string) if !ok { return fmt.Errorf(`expected a list of glob patterns but got "%v" of type %T`, v, v) } for _, pat := range globPatterns { op.TemplatePatterns = append(op.TemplatePatterns, strings.TrimSpace(pat)) } return nil } if v, ok := config["path"]; ok { globPatternStr, ok := v.(string) if !ok { return fmt.Errorf(`expected a glob pattern but got "%v" of type %T`, v, v) } op.TemplatePatterns = []string{strings.TrimSpace(globPatternStr)} return nil } return fmt.Errorf(`invalid config`) } func (op Layout) ProcessItem(content cabret.Content) (*cabret.Content, error) { // expand glob patterns tmplFiles := []string{} for _, pat := range op.TemplatePatterns { files, err := filepath.Glob(strings.TrimSpace(pat)) if err != nil { return nil, err } tmplFiles = append(tmplFiles, files...) } // create template tmpl, err := template.ParseFiles(tmplFiles...) if err != nil { return nil, err } ctx := util.CloneMap(content.Metadata) if content.Type == HtmlMimeType { ctx["Content"] = goHtmlTemplate.HTML(content.Data) } else { ctx["Content"] = content.Data } log.Printf(`[operation.Layout] rendering into layout "%s"`, strings.Join(op.TemplatePatterns, ", ")) data, err := tmpl.Render(ctx) if err != nil { return nil, err } content.Data = data return &content, nil }