initial commit

main
Antonio De Lucreziis 2 years ago
commit 7d22424cf1

4
.gitignore vendored

@ -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…
Cancel
Save