add: pipeline categorization by metadata key
This commit is contained in:
+45
-5
@@ -2,8 +2,10 @@ package operation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aziis98/cabret"
|
||||
"github.com/iancoleman/strcase"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -12,9 +14,6 @@ func init() {
|
||||
|
||||
type Categorize struct {
|
||||
Key string
|
||||
|
||||
// Operation to be executed for each category
|
||||
Operation cabret.Operation
|
||||
}
|
||||
|
||||
func (op *Categorize) Load(config map[string]any) error {
|
||||
@@ -34,6 +33,47 @@ func (op *Categorize) Load(config map[string]any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *Categorize) Process(content cabret.Content) (*cabret.Content, error) {
|
||||
return nil, nil
|
||||
func (op *Categorize) ProcessList(contents []cabret.Content) ([]cabret.Content, error) {
|
||||
key := strcase.ToCamel(op.Key)
|
||||
|
||||
categories := map[string][]cabret.Content{}
|
||||
|
||||
for _, content := range contents {
|
||||
v, ok := content.Metadata[key]
|
||||
if !ok {
|
||||
log.Printf(`[operation.Categorize] item has no categories`)
|
||||
continue
|
||||
}
|
||||
|
||||
cats, ok := v.([]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`expected a list but got "%v" of type %T`, v, v)
|
||||
}
|
||||
|
||||
for _, v := range cats {
|
||||
cat, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`expected a string but got "%v" of type %T`, v, v)
|
||||
}
|
||||
|
||||
log.Printf(`[operation.Categorize] found item with category "%s"`, cat)
|
||||
|
||||
categories[cat] = append(categories[cat], content)
|
||||
}
|
||||
}
|
||||
|
||||
result := []cabret.Content{}
|
||||
for name, contents := range categories {
|
||||
log.Printf(`[operation.Categorize] generating category with %v item(s)`, len(contents))
|
||||
|
||||
result = append(result, cabret.Content{
|
||||
Type: "metadata-only",
|
||||
Metadata: cabret.Map{
|
||||
"Category": name,
|
||||
"Items": contents,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package operation
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/aziis98/cabret"
|
||||
"github.com/iancoleman/strcase"
|
||||
"github.com/yuin/goldmark"
|
||||
meta "github.com/yuin/goldmark-meta"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerType("frontmatter", &Frontmatter{})
|
||||
}
|
||||
|
||||
type Frontmatter struct {
|
||||
Options map[string]any
|
||||
}
|
||||
|
||||
func (op *Frontmatter) Load(config map[string]any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *Frontmatter) ProcessItem(content cabret.Content) (*cabret.Content, error) {
|
||||
md := goldmark.New(
|
||||
goldmark.WithExtensions(
|
||||
meta.Meta,
|
||||
),
|
||||
)
|
||||
|
||||
log.Printf(`[operation.Frontmatter] reading frontmatter`)
|
||||
|
||||
context := parser.NewContext()
|
||||
if err := md.Convert(content.Data, io.Discard, parser.WithContext(context)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
frontmatter := meta.Get(context)
|
||||
for k, v := range frontmatter {
|
||||
content.Metadata[strcase.ToCamel(k)] = v
|
||||
}
|
||||
|
||||
return &content, nil
|
||||
}
|
||||
@@ -97,6 +97,7 @@ func (op Layout) ProcessItem(content cabret.Content) (*cabret.Content, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content.Type = mime.TypeByExtension(filepath.Ext(tmplFiles[0]))
|
||||
content.Data = data
|
||||
return &content, nil
|
||||
}
|
||||
|
||||
+27
-4
@@ -1,9 +1,12 @@
|
||||
package operation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
txtTemplate "text/template"
|
||||
|
||||
gopath "path"
|
||||
|
||||
@@ -34,12 +37,32 @@ func (op *Target) Load(config map[string]any) error {
|
||||
}
|
||||
|
||||
func (op Target) ProcessItem(c cabret.Content) (*cabret.Content, error) {
|
||||
mr, ok := c.Metadata[cabret.MatchResultKey].(map[string]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`invalid match result type %T`, c.Metadata[cabret.MatchResultKey])
|
||||
log.Printf(`[operation.Target] expanding pattern "%s"`, op.PathTemplate)
|
||||
|
||||
target := op.PathTemplate
|
||||
|
||||
if strings.Contains(target, "{{") {
|
||||
t, err := txtTemplate.New("path").Parse(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := t.Execute(&buf, c.Metadata); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
target = buf.String()
|
||||
}
|
||||
|
||||
target := path.RenderTemplate(op.PathTemplate, mr)
|
||||
if v, ok := c.Metadata[cabret.MatchResultKey]; ok {
|
||||
context, ok := v.(map[string]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`invalid match result type %T`, c.Metadata[cabret.MatchResultKey])
|
||||
}
|
||||
|
||||
target = path.RenderTemplate(target, context)
|
||||
}
|
||||
|
||||
log.Printf(`[operation.Target] writing "%s"`, target)
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package operation
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "log"
|
||||
// "mime"
|
||||
// "path/filepath"
|
||||
// "strings"
|
||||
|
||||
// "github.com/aziis98/cabret"
|
||||
// "github.com/aziis98/cabret/operation/template"
|
||||
// )
|
||||
|
||||
// func init() {
|
||||
// registerType("template", &Template{})
|
||||
// }
|
||||
|
||||
// type Template struct {
|
||||
// // TemplatePatterns is a list of glob patterns of templates that will be loaded
|
||||
// TemplatePatterns []string
|
||||
// }
|
||||
|
||||
// func (op *Template) 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 for "template": %#v`, config)
|
||||
// }
|
||||
|
||||
// func (op *Template) ProcessList(contents []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
|
||||
// }
|
||||
|
||||
// log.Printf(`[operation.Layout] rendering into layout "%s"`, strings.Join(op.TemplatePatterns, ", "))
|
||||
|
||||
// ctx := map[string]any{}
|
||||
// ctx["Items"] = contents
|
||||
// data, err := tmpl.Render(ctx)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// return []cabret.Content{
|
||||
// {
|
||||
// Type: mime.TypeByExtension(filepath.Ext(tmplFiles[0])),
|
||||
// Data: data,
|
||||
// Metadata: ctx,
|
||||
// },
|
||||
// }, nil
|
||||
// }
|
||||
@@ -5,7 +5,13 @@ import (
|
||||
goHtmlTemplate "html/template"
|
||||
)
|
||||
|
||||
var _ Template = HtmlTemplate{}
|
||||
func safeHTML(str string) goHtmlTemplate.HTML {
|
||||
return goHtmlTemplate.HTML(str)
|
||||
}
|
||||
|
||||
var fn = goHtmlTemplate.FuncMap{
|
||||
"html": safeHTML,
|
||||
}
|
||||
|
||||
type HtmlTemplate struct {
|
||||
*goHtmlTemplate.Template
|
||||
@@ -17,6 +23,8 @@ func NewHtmlTemplate(files ...string) (*HtmlTemplate, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.Funcs(fn)
|
||||
|
||||
return &HtmlTemplate{t}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user