Rewrite to new yaml format
parent
9ebc4715ed
commit
46715cf033
@ -1,4 +1,7 @@
|
||||
|
||||
.env
|
||||
*.local*
|
||||
bin/
|
||||
dist/
|
||||
|
||||
.vscode/
|
||||
|
@ -1,12 +1,14 @@
|
||||
entryPoints:
|
||||
- source: index.html
|
||||
pipeline:
|
||||
- layout: layouts/base.html
|
||||
build:
|
||||
- pipeline:
|
||||
- source: index.html
|
||||
- use: layout
|
||||
path: layouts/base.html
|
||||
- target: dist/index.html
|
||||
- source: posts/{id}.md
|
||||
pipeline:
|
||||
- plugin: markdown
|
||||
- layout: layouts/base.html
|
||||
- pipeline:
|
||||
- source: posts/{id}.md
|
||||
- use: markdown
|
||||
- use: layout
|
||||
path: layouts/base.html
|
||||
- target: dist/posts/{id}/index.html
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<h1>My Website</h1>
|
||||
|
||||
<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>
|
||||
|
@ -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