Rewrite to new yaml format
parent
9ebc4715ed
commit
46715cf033
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
.env
|
||||||
*.local*
|
*.local*
|
||||||
bin/
|
bin/
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
entryPoints:
|
build:
|
||||||
- source: index.html
|
- pipeline:
|
||||||
pipeline:
|
- source: index.html
|
||||||
- layout: layouts/base.html
|
- use: layout
|
||||||
|
path: layouts/base.html
|
||||||
- target: dist/index.html
|
- target: dist/index.html
|
||||||
- source: posts/{id}.md
|
- pipeline:
|
||||||
pipeline:
|
- source: posts/{id}.md
|
||||||
- plugin: markdown
|
- use: markdown
|
||||||
- layout: layouts/base.html
|
- use: layout
|
||||||
|
path: layouts/base.html
|
||||||
- target: dist/posts/{id}/index.html
|
- target: dist/posts/{id}/index.html
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<h1>My Website</h1>
|
<h1>My Website</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Minima, eveniet, dolorum amet, cupiditate quae excepturi aspernatur dolor voluptatem obcaecati ratione quas? Et explicabo illum iure eius porro, dolor quos doloremque!
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Minima, eveniet, dolorum amet, cupiditate quae excepturi aspernatur dolor
|
||||||
|
voluptatem obcaecati ratione quas? Et explicabo illum iure eius porro, dolor quos doloremque!
|
||||||
</p>
|
</p>
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package operation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aziis98/cabret"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerType("categorize", &Categorize{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Categorize struct {
|
||||||
|
Key string
|
||||||
|
|
||||||
|
// Operation to be executed for each category
|
||||||
|
Operation cabret.Operation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *Categorize) Load(config map[string]any) error {
|
||||||
|
{
|
||||||
|
v, ok := config["key"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf(`missing "key" field`)
|
||||||
|
}
|
||||||
|
key, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf(`expected string but got "%v" of type %T`, v, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
op.Key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *Categorize) Process(content cabret.Content) (*cabret.Content, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package operation
|
|
||||||
|
|
||||||
import "github.com/aziis98/cabret"
|
|
||||||
|
|
||||||
type GroupBy struct {
|
|
||||||
Key string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (op GroupBy) Process(content cabret.Content) (*cabret.Content, error) {
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package layout
|
|
||||||
|
|
||||||
type Template interface {
|
|
||||||
Render(ctx map[string]any) ([]byte, error)
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package operation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"mime"
|
|
||||||
"os"
|
|
||||||
gopath "path"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/aziis98/cabret"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ cabret.ListOperation = Read{}
|
|
||||||
|
|
||||||
type Read struct {
|
|
||||||
Patterns []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (op Read) MapAll(contents []cabret.Content) ([]cabret.Content, error) {
|
|
||||||
for _, pattern := range op.Patterns {
|
|
||||||
files, err := filepath.Glob(pattern)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
data, err := os.ReadFile(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contents = append(contents, cabret.Content{
|
|
||||||
Type: mime.TypeByExtension(gopath.Ext(file)),
|
|
||||||
Data: data,
|
|
||||||
Metadata: cabret.Map{},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return contents, nil
|
|
||||||
}
|
|
@ -0,0 +1,34 @@
|
|||||||
|
package operation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/aziis98/cabret"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ShortFormValueKey is used by some operations that support an inline form
|
||||||
|
const ShortFormValueKey = "value"
|
||||||
|
|
||||||
|
var registry = map[string]reflect.Type{}
|
||||||
|
|
||||||
|
func registerType(name string, op cabret.Operation) {
|
||||||
|
typ := reflect.TypeOf(op).Elem()
|
||||||
|
log.Printf(`[operation] registered type "%v"`, typ)
|
||||||
|
registry[name] = typ
|
||||||
|
}
|
||||||
|
|
||||||
|
func Build(name string, options map[string]any) (cabret.Operation, error) {
|
||||||
|
typ, ok := registry[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf(`no registered operation named %q`, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
op := reflect.New(typ).Interface().(cabret.Operation)
|
||||||
|
if err := op.Load(options); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return op, nil
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package operation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuild(t *testing.T) {
|
||||||
|
op, err := Build("categorize", map[string]any{
|
||||||
|
"key": "tags",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.DeepEqual(t, op, &Categorize{
|
||||||
|
Key: "tags",
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package operation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"mime"
|
||||||
|
"os"
|
||||||
|
gopath "path"
|
||||||
|
|
||||||
|
"github.com/aziis98/cabret"
|
||||||
|
"github.com/aziis98/cabret/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerType("source", &Source{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source is a ListOperation that appends the matched files to the processing items
|
||||||
|
type Source struct {
|
||||||
|
Patterns []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *Source) Load(config map[string]any) error {
|
||||||
|
if v, ok := config[ShortFormValueKey]; ok {
|
||||||
|
pattern, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf(`expected pattern but got "%v" of type %T`, v, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
op.Patterns = []string{pattern}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if v, ok := config["paths"]; ok {
|
||||||
|
patterns, ok := v.([]string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf(`expected list of patterns but got "%v" of type %T`, v, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
op.Patterns = patterns
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf(`invalid config for "source": %#v`, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op Source) ProcessList(contents []cabret.Content) ([]cabret.Content, error) {
|
||||||
|
files, err := cabret.FindFiles([]string{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := []cabret.MatchResult{}
|
||||||
|
|
||||||
|
for _, patternStr := range op.Patterns {
|
||||||
|
pat, err := path.ParsePattern(patternStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
if ok, captures, _ := pat.Match(f); ok {
|
||||||
|
matches = append(matches, cabret.MatchResult{
|
||||||
|
File: f,
|
||||||
|
Captures: captures,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range matches {
|
||||||
|
log.Printf(`[operation.Source] reading "%s"`, m.File)
|
||||||
|
|
||||||
|
data, err := os.ReadFile(m.File)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = append(contents, cabret.Content{
|
||||||
|
Type: mime.TypeByExtension(gopath.Ext(m.File)),
|
||||||
|
Data: data,
|
||||||
|
Metadata: cabret.Map{
|
||||||
|
cabret.MatchResultKey: m.Captures,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents, nil
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Template interface {
|
||||||
|
Render(ctx map[string]any) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseFiles(files ...string) (Template, error) {
|
||||||
|
if filepath.Ext(files[0]) == ".html" {
|
||||||
|
return NewHtmlTemplate(files...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTextTemplate(files...)
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package pipeline
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aziis98/cabret"
|
||||||
|
"github.com/aziis98/cabret/config"
|
||||||
|
"github.com/aziis98/cabret/operation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func switchMap(m map[string]any, v *any) func(k string) bool {
|
||||||
|
return func(k string) bool {
|
||||||
|
val, ok := m[k]
|
||||||
|
if ok {
|
||||||
|
*v = val
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(p config.Pipeline) ([]cabret.Operation, error) {
|
||||||
|
ops := []cabret.Operation{}
|
||||||
|
|
||||||
|
for _, opConfig := range p.Pipeline {
|
||||||
|
var v any
|
||||||
|
has := switchMap(opConfig, &v)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case has("source"):
|
||||||
|
value, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf(`expected string but got "%v" of type %T`, v, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
opConfig[operation.ShortFormValueKey] = value
|
||||||
|
op := &operation.Source{}
|
||||||
|
if err := op.Load(opConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ops = append(ops, op)
|
||||||
|
|
||||||
|
case has("target"):
|
||||||
|
value, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf(`expected string but got "%v" of type %T`, v, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
opConfig[operation.ShortFormValueKey] = value
|
||||||
|
op := &operation.Target{}
|
||||||
|
if err := op.Load(opConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ops = append(ops, op)
|
||||||
|
|
||||||
|
case has("use"):
|
||||||
|
name, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf(`expected string but got "%v" of type %T`, v, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
op, err := operation.Build(name, opConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ops = append(ops, op)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf(`pipeline entry is missing one of "use", "source" or "target", got %#v`, opConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ops, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Process(contents []cabret.Content, ops []cabret.Operation) ([]cabret.Content, error) {
|
||||||
|
for _, op := range ops {
|
||||||
|
var err error
|
||||||
|
contents, err = cabret.ProcessOperation(op, contents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents, nil
|
||||||
|
}
|
Loading…
Reference in New Issue