Minimal working prototype
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package operation
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
gopath "path"
|
||||
|
||||
"github.com/alecthomas/repr"
|
||||
"github.com/aziis98/cabret"
|
||||
"github.com/aziis98/cabret/operation/layout"
|
||||
"github.com/aziis98/cabret/util"
|
||||
)
|
||||
|
||||
var HtmlMimeType = mime.TypeByExtension(".html")
|
||||
|
||||
var _ cabret.Operation = Layout{}
|
||||
|
||||
type Layout struct {
|
||||
// TemplateFilesPattern is a comma separated list of unix glob patterns
|
||||
TemplateFilesPattern string
|
||||
|
||||
Options map[string]any
|
||||
}
|
||||
|
||||
func (op Layout) Process(content cabret.Content) (*cabret.Content, error) {
|
||||
var tmpl layout.Template
|
||||
|
||||
patterns := strings.Split(op.TemplateFilesPattern, ",")
|
||||
|
||||
tmplFiles := []string{}
|
||||
for _, pat := range patterns {
|
||||
files, err := filepath.Glob(strings.TrimSpace(pat))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tmplFiles = append(tmplFiles, files...)
|
||||
}
|
||||
|
||||
log.Printf(`[Layout] template pattern "%s" expanded to %s`, op.TemplateFilesPattern, repr.String(tmplFiles))
|
||||
|
||||
if gopath.Ext(tmplFiles[0]) == ".html" {
|
||||
var err error
|
||||
if tmpl, err = layout.NewHtmlTemplate(tmplFiles...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
if tmpl, err = layout.NewTextTemplate(tmplFiles...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ctx := util.CloneMap(content.Metadata)
|
||||
|
||||
if content.Type == HtmlMimeType {
|
||||
ctx["Content"] = template.HTML(content.Data)
|
||||
} else {
|
||||
ctx["Content"] = content.Data
|
||||
}
|
||||
|
||||
data, err := tmpl.Render(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content.Data = data
|
||||
return &content, nil
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package layout
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
var _ Template = HtmlTemplate{}
|
||||
|
||||
type HtmlTemplate struct {
|
||||
*template.Template
|
||||
}
|
||||
|
||||
func NewHtmlTemplate(files ...string) (*HtmlTemplate, error) {
|
||||
t, err := template.ParseFiles(files...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &HtmlTemplate{t}, nil
|
||||
}
|
||||
|
||||
func (t HtmlTemplate) Render(ctx map[string]any) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
|
||||
if err := t.Template.Execute(&b, ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package layout
|
||||
|
||||
type Template interface {
|
||||
Render(ctx map[string]any) ([]byte, error)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package layout
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var _ Template = TextTemplate{}
|
||||
|
||||
type TextTemplate struct {
|
||||
*template.Template
|
||||
}
|
||||
|
||||
func NewTextTemplate(files ...string) (*TextTemplate, error) {
|
||||
t, err := template.ParseFiles(files...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &TextTemplate{t}, nil
|
||||
}
|
||||
|
||||
func (t TextTemplate) Render(ctx map[string]any) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
|
||||
if err := t.Template.Execute(&b, ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package operation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/aziis98/cabret"
|
||||
"github.com/iancoleman/strcase"
|
||||
"github.com/yuin/goldmark"
|
||||
meta "github.com/yuin/goldmark-meta"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
)
|
||||
|
||||
type Markdown struct {
|
||||
Options map[string]any
|
||||
}
|
||||
|
||||
func (op Markdown) Process(content cabret.Content) (*cabret.Content, error) {
|
||||
md := goldmark.New(
|
||||
goldmark.WithExtensions(
|
||||
extension.GFM,
|
||||
meta.Meta,
|
||||
),
|
||||
goldmark.WithParserOptions(
|
||||
parser.WithAutoHeadingID(),
|
||||
),
|
||||
)
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
context := parser.NewContext()
|
||||
if err := md.Convert(content.Data, &buf, parser.WithContext(context)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
frontmatter := meta.Get(context)
|
||||
for k, v := range frontmatter {
|
||||
content.Metadata[strcase.ToCamel(k)] = v
|
||||
}
|
||||
|
||||
return &cabret.Content{
|
||||
Type: HtmlMimeType,
|
||||
Data: buf.Bytes(),
|
||||
Metadata: content.Metadata,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package operation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
gopath "path"
|
||||
|
||||
"github.com/aziis98/cabret"
|
||||
"github.com/aziis98/cabret/path"
|
||||
)
|
||||
|
||||
var _ cabret.Operation = Target{}
|
||||
|
||||
type Target struct {
|
||||
PathTemplate string
|
||||
}
|
||||
|
||||
func (op Target) Process(c cabret.Content) (*cabret.Content, error) {
|
||||
mr, ok := c.Metadata[cabret.MatchResult].(map[string]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`invalid match result type %T`, c.Metadata[cabret.MatchResult])
|
||||
}
|
||||
|
||||
target := path.RenderTemplate(op.PathTemplate, mr)
|
||||
|
||||
if err := os.MkdirAll(gopath.Dir(target), 0777); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.WriteFile(target, c.Data, 0666); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Metadata["Target"] = op.PathTemplate
|
||||
return &c, nil
|
||||
}
|
||||
Reference in New Issue
Block a user