initial commit
commit
7d22424cf1
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
*.local*
|
||||||
|
bin/
|
||||||
|
dist/
|
@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/alecthomas/repr"
|
||||||
|
"github.com/aziis98/cabret/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.Printf("Rendering current project")
|
||||||
|
|
||||||
|
site, err := config.ParseCabretfile("./Cabretfile.yaml")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repr.Println(site)
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operation is an enum of various operations
|
||||||
|
type Operation struct {
|
||||||
|
Layout string `yaml:"layout,omitempty"`
|
||||||
|
Target string `yaml:"target,omitempty"`
|
||||||
|
Plugin string `yaml:"plugin,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntryPoint struct {
|
||||||
|
Source string `yaml:"source"`
|
||||||
|
Pipeline []Operation `yaml:"pipeline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Output string `yaml:"output,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Site has some configuration for the
|
||||||
|
type Site struct {
|
||||||
|
Config Config `yaml:"config,omitempty"`
|
||||||
|
EntryPoints []EntryPoint `yaml:"entry-points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseCabretfile(file string) (*Site, error) {
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
site := new(Site)
|
||||||
|
if err := yaml.NewDecoder(f).Decode(&site); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return site, nil
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
site:
|
||||||
|
entry-points:
|
||||||
|
- source: index.html
|
||||||
|
pipeline:
|
||||||
|
- layout: layouts/base
|
||||||
|
- target: dist/index.html
|
||||||
|
- source: 'posts/{post-name}.md'
|
||||||
|
pipeline:
|
||||||
|
- plugin: markdown
|
||||||
|
- layout: layouts/base
|
||||||
|
- layout: layouts/post.html
|
||||||
|
- target: 'dist/posts/{post-name}/index.html'
|
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>{{ .Metadata.Title }}</title>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: First Post
|
||||||
|
description: Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||||
|
publish_date: 2022-12-22 11:00
|
||||||
|
---
|
||||||
|
|
||||||
|
# First Post
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Beatae ratione eos saepe veritatis, temporibus nemo vero rerum earum voluptatibus minus voluptatem neque consequatur necessitatibus, error magnam deserunt! Ad, accusantium excepturi?
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Beatae ratione eos saepe veritatis, temporibus nemo vero rerum earum voluptatibus minus voluptatem neque consequatur necessitatibus, error magnam deserunt! Ad, accusantium excepturi?
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: Second Post
|
||||||
|
description: Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||||
|
publish_date: 2022-12-22 11:00
|
||||||
|
---
|
||||||
|
|
||||||
|
# Second Post
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Beatae ratione eos saepe veritatis, temporibus nemo vero rerum earum voluptatibus minus voluptatem neque consequatur necessitatibus, error magnam deserunt! Ad, accusantium excepturi?
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Beatae ratione eos saepe veritatis, temporibus nemo vero rerum earum voluptatibus minus voluptatem neque consequatur necessitatibus, error magnam deserunt! Ad, accusantium excepturi?
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: Third Post
|
||||||
|
description: Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||||
|
publish_date: 2022-12-22 11:00
|
||||||
|
---
|
||||||
|
|
||||||
|
# Third Post
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Beatae ratione eos saepe veritatis, temporibus nemo vero rerum earum voluptatibus minus voluptatem neque consequatur necessitatibus, error magnam deserunt! Ad, accusantium excepturi?
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Beatae ratione eos saepe veritatis, temporibus nemo vero rerum earum voluptatibus minus voluptatem neque consequatur necessitatibus, error magnam deserunt! Ad, accusantium excepturi?
|
@ -0,0 +1,13 @@
|
|||||||
|
module github.com/aziis98/cabret
|
||||||
|
|
||||||
|
go 1.19
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/alecthomas/participle/v2 v2.0.0-beta.5 // indirect
|
||||||
|
github.com/alecthomas/repr v0.1.1 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/yuin/goldmark v1.5.3 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
gotest.tools v2.2.0+incompatible // indirect
|
||||||
|
)
|
@ -0,0 +1,15 @@
|
|||||||
|
github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35a3WghArZ/Hbebrjo=
|
||||||
|
github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM=
|
||||||
|
github.com/alecthomas/repr v0.1.1 h1:87P60cSmareLAxMc4Hro0r2RBY4ROm0dYwkJNpS4pPs=
|
||||||
|
github.com/alecthomas/repr v0.1.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M=
|
||||||
|
github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
@ -0,0 +1,111 @@
|
|||||||
|
package path
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alecthomas/participle/v2"
|
||||||
|
"github.com/alecthomas/participle/v2/lexer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PathPart interface {
|
||||||
|
regex() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathSlash struct {
|
||||||
|
Value string `"/"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PathSlash) regex() string {
|
||||||
|
return "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathShortPattern struct {
|
||||||
|
Name string `"{" @Ident "}"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PathShortPattern) regex() string {
|
||||||
|
return fmt.Sprintf("(?P<%s>[^/]+?)", p.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathLongPattern struct {
|
||||||
|
Name string `"{{" @Ident "}}"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PathLongPattern) regex() string {
|
||||||
|
return fmt.Sprintf("(?P<%s>.+?)", p.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathString struct {
|
||||||
|
Value string `@Ident`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PathString) regex() string {
|
||||||
|
return regexp.QuoteMeta(p.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathPattern struct {
|
||||||
|
Parts []PathPart `@@+`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pp PathPattern) regex() string {
|
||||||
|
sb := &strings.Builder{}
|
||||||
|
|
||||||
|
for _, p := range pp.Parts {
|
||||||
|
sb.WriteString(p.regex())
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pp PathPattern) Match(s string) (bool, map[string]string, error) {
|
||||||
|
r, err := regexp.Compile("^" + pp.regex() + "$")
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ms := r.FindStringSubmatch(s)
|
||||||
|
if ms == nil {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := map[string]string{}
|
||||||
|
for i, name := range r.SubexpNames() {
|
||||||
|
ctx[name] = ms[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, ctx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var parser = participle.MustBuild[PathPattern](
|
||||||
|
participle.Union[PathPart](
|
||||||
|
&PathSlash{},
|
||||||
|
&PathLongPattern{},
|
||||||
|
&PathShortPattern{},
|
||||||
|
&PathString{},
|
||||||
|
),
|
||||||
|
participle.Lexer(
|
||||||
|
lexer.MustSimple([]lexer.SimpleRule{
|
||||||
|
{Name: "Slash", Pattern: `/`},
|
||||||
|
{Name: "PatternLongOpen", Pattern: `{{`},
|
||||||
|
{Name: "PatternLongClose", Pattern: `}}`},
|
||||||
|
{Name: "PatternShortOpen", Pattern: `{`},
|
||||||
|
{Name: "PatternShortClose", Pattern: `}`},
|
||||||
|
{Name: "Ident", Pattern: `[^/{}]+`},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParsePattern(path string) (*PathPattern, error) {
|
||||||
|
return parser.ParseString("", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MustParsePattern(path string) *PathPattern {
|
||||||
|
p, err := ParsePattern(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package path_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aziis98/cabret/path"
|
||||||
|
"gotest.tools/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test1(t *testing.T) {
|
||||||
|
p, err := path.ParsePattern("/foo/bar")
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.DeepEqual(t, p, &path.PathPattern{
|
||||||
|
Parts: []path.PathPart{
|
||||||
|
&path.PathSlash{}, &path.PathString{"foo"}, &path.PathSlash{}, &path.PathString{"bar"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test2(t *testing.T) {
|
||||||
|
p, err := path.ParsePattern("posts/{name}.md")
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.DeepEqual(t, p, &path.PathPattern{
|
||||||
|
Parts: []path.PathPart{
|
||||||
|
&path.PathString{"posts"}, &path.PathSlash{}, &path.PathShortPattern{"name"}, &path.PathString{".md"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test3(t *testing.T) {
|
||||||
|
p, err := path.ParsePattern("posts/{{path}}/{name}.md")
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.DeepEqual(t, p, &path.PathPattern{
|
||||||
|
Parts: []path.PathPart{
|
||||||
|
&path.PathString{"posts"},
|
||||||
|
&path.PathSlash{},
|
||||||
|
&path.PathLongPattern{"path"},
|
||||||
|
&path.PathSlash{},
|
||||||
|
&path.PathShortPattern{"name"},
|
||||||
|
&path.PathString{".md"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test4(t *testing.T) {
|
||||||
|
p, err := path.ParsePattern("foo{{path}}/{name}.md")
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.DeepEqual(t, p, &path.PathPattern{
|
||||||
|
Parts: []path.PathPart{
|
||||||
|
&path.PathString{"foo"},
|
||||||
|
&path.PathLongPattern{"path"},
|
||||||
|
&path.PathSlash{},
|
||||||
|
&path.PathShortPattern{"name"},
|
||||||
|
&path.PathString{".md"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("match", func(t *testing.T) {
|
||||||
|
m, ctx, err := p.Match("foo-1/bar/baz/post-1.md")
|
||||||
|
|
||||||
|
assert.NilError(t, err, nil)
|
||||||
|
assert.Equal(t, m, true)
|
||||||
|
assert.DeepEqual(t, ctx, map[string]string{
|
||||||
|
"": "foo-1/bar/baz/post-1.md",
|
||||||
|
"name": "post-1",
|
||||||
|
"path": "-1/bar/baz",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue