add support for data files

This commit is contained in:
facundoolano 2024-02-15 16:01:35 -03:00
parent 180a5c7ac1
commit ed258fddc4
4 changed files with 91 additions and 16 deletions

View file

@ -10,6 +10,7 @@ import (
const SRC_DIR = "src" const SRC_DIR = "src"
const TARGET_DIR = "target" const TARGET_DIR = "target"
const LAYOUTS_DIR = "layouts" const LAYOUTS_DIR = "layouts"
const DATA_DIR = "data"
func Init() error { func Init() error {
// get working directory // get working directory
@ -35,8 +36,9 @@ func Build(root string) error {
src := filepath.Join(root, SRC_DIR) src := filepath.Join(root, SRC_DIR)
target := filepath.Join(root, TARGET_DIR) target := filepath.Join(root, TARGET_DIR)
layouts := filepath.Join(root, LAYOUTS_DIR) layouts := filepath.Join(root, LAYOUTS_DIR)
data := filepath.Join(root, DATA_DIR)
site, err := site.Load(src, layouts) site, err := site.Load(src, layouts, data)
if err != nil { if err != nil {
return err return err
} }

View file

@ -35,7 +35,7 @@ func Serve() error {
} }
func rebuild() error { func rebuild() error {
site, err := site.Load(SRC_DIR, LAYOUTS_DIR) site, err := site.Load(SRC_DIR, LAYOUTS_DIR, DATA_DIR)
if err != nil { if err != nil {
return err return err
} }

View file

@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/facundoolano/blorg/templates" "github.com/facundoolano/blorg/templates"
"gopkg.in/yaml.v3"
) )
const FILE_RW_MODE = 0777 const FILE_RW_MODE = 0777
@ -22,21 +23,27 @@ type Site struct {
posts []map[string]interface{} posts []map[string]interface{}
pages []map[string]interface{} pages []map[string]interface{}
tags map[string][]map[string]interface{} tags map[string][]map[string]interface{}
data map[string]interface{}
templateEngine *templates.Engine templateEngine *templates.Engine
templates map[string]*templates.Template templates map[string]*templates.Template
} }
func Load(srcDir string, layoutsDir string) (*Site, error) { func Load(srcDir string, layoutsDir string, dataDir string) (*Site, error) {
// TODO load config from config.yml // TODO load config from config.yml
site := Site{ site := Site{
layouts: make(map[string]templates.Template), layouts: make(map[string]templates.Template),
templates: make(map[string]*templates.Template), templates: make(map[string]*templates.Template),
config: make(map[string]string), config: make(map[string]string),
tags: make(map[string][]map[string]interface{}), tags: make(map[string][]map[string]interface{}),
data: make(map[string]interface{}),
templateEngine: templates.NewEngine(), templateEngine: templates.NewEngine(),
} }
if err := site.loadDataFiles(dataDir); err != nil {
return nil, err
}
if err := site.loadLayouts(layoutsDir); err != nil { if err := site.loadLayouts(layoutsDir); err != nil {
return nil, err return nil, err
} }
@ -74,6 +81,38 @@ func (site *Site) loadLayouts(layoutsDir string) error {
return nil return nil
} }
func (site *Site) loadDataFiles(dataDir string) error {
files, err := os.ReadDir(dataDir)
if os.IsNotExist(err) {
return nil
} else if err != nil {
return err
}
for _, entry := range files {
if !entry.IsDir() {
filename := entry.Name()
path := filepath.Join(dataDir, filename)
yamlContent, err := os.ReadFile(path)
if err != nil {
return err
}
var data interface{}
err = yaml.Unmarshal(yamlContent, &data)
if err != nil {
return err
}
data_name := strings.TrimSuffix(filename, filepath.Ext(filename))
site.data[data_name] = data
}
}
return nil
}
func (site *Site) loadTemplates(srcDir string) error { func (site *Site) loadTemplates(srcDir string) error {
_, err := os.ReadDir(srcDir) _, err := os.ReadDir(srcDir)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -206,6 +245,7 @@ func (site Site) render(templ *templates.Template) ([]byte, error) {
"posts": site.posts, "posts": site.posts,
"tags": site.tags, "tags": site.tags,
"pages": site.pages, "pages": site.pages,
"data": site.data,
}, },
} }

View file

@ -7,7 +7,7 @@ import (
) )
func TestLoadAndRenderTemplates(t *testing.T) { func TestLoadAndRenderTemplates(t *testing.T) {
root, layouts, src := newProject() root, layouts, src, data := newProject()
defer os.RemoveAll(root) defer os.RemoveAll(root)
// add two layouts // add two layouts
@ -68,7 +68,7 @@ title: about
content = `go away!` content = `go away!`
file = newFile(src, "robots.txt", content) file = newFile(src, "robots.txt", content)
site, err := Load(src, layouts) site, err := Load(src, layouts, data)
assertEqual(t, err, nil) assertEqual(t, err, nil)
@ -115,7 +115,7 @@ title: about
} }
func TestRenderArchive(t *testing.T) { func TestRenderArchive(t *testing.T) {
root, layouts, src := newProject() root, layouts, src, data := newProject()
defer os.RemoveAll(root) defer os.RemoveAll(root)
content := `--- content := `---
@ -152,7 +152,7 @@ date: 2023-01-01
file = newFile(src, "about.html", content) file = newFile(src, "about.html", content)
defer os.Remove(file.Name()) defer os.Remove(file.Name())
site, err := Load(src, layouts) site, err := Load(src, layouts, data)
output, err := site.render(site.templates[file.Name()]) output, err := site.render(site.templates[file.Name()])
assertEqual(t, err, nil) assertEqual(t, err, nil)
assertEqual(t, string(output), `<ul> assertEqual(t, string(output), `<ul>
@ -163,7 +163,7 @@ date: 2023-01-01
} }
func TestRenderTags(t *testing.T) { func TestRenderTags(t *testing.T) {
root, layouts, src := newProject() root, layouts, src, data := newProject()
defer os.RemoveAll(root) defer os.RemoveAll(root)
content := `--- content := `---
@ -205,7 +205,7 @@ tags: [software]
file = newFile(src, "about.html", content) file = newFile(src, "about.html", content)
defer os.Remove(file.Name()) defer os.Remove(file.Name())
site, err := Load(src, layouts) site, err := Load(src, layouts, data)
output, err := site.render(site.templates[file.Name()]) output, err := site.render(site.templates[file.Name()])
assertEqual(t, err, nil) assertEqual(t, err, nil)
assertEqual(t, string(output), `<h1>software</h1> assertEqual(t, string(output), `<h1>software</h1>
@ -222,7 +222,7 @@ hello world!
} }
func TestRenderPagesInDir(t *testing.T) { func TestRenderPagesInDir(t *testing.T) {
root, layouts, src := newProject() root, layouts, src, data := newProject()
defer os.RemoveAll(root) defer os.RemoveAll(root)
content := `--- content := `---
@ -256,7 +256,7 @@ title: "2. an oldie!"
file = newFile(src, "index.html", content) file = newFile(src, "index.html", content)
defer os.Remove(file.Name()) defer os.Remove(file.Name())
site, err := Load(src, layouts) site, err := Load(src, layouts, data)
output, err := site.render(site.templates[file.Name()]) output, err := site.render(site.templates[file.Name()])
assertEqual(t, err, nil) assertEqual(t, err, nil)
assertEqual(t, string(output), `<ul> assertEqual(t, string(output), `<ul>
@ -271,24 +271,57 @@ func TestRenderArchiveWithExcerpts(t *testing.T) {
} }
func TestRenderDataFile(t *testing.T) { func TestRenderDataFile(t *testing.T) {
// TODO root, layouts, src, data := newProject()
defer os.RemoveAll(root)
content := `
- name: feedi
url: https://github.com/facundoolano/feedi
- name: blorg
url: https://github.com/facundoolano/blorg
`
file := newFile(data, "projects.yml", content)
defer os.Remove(file.Name())
// add a page (no date)
content = `---
---
<ul>{% for project in site.data.projects %}
<li><a href="{{ project.url }}">{{project.name}}</a></li>{%endfor%}
</ul>`
file = newFile(src, "projects.html", content)
defer os.Remove(file.Name())
site, err := Load(src, layouts, data)
output, err := site.render(site.templates[file.Name()])
assertEqual(t, err, nil)
assertEqual(t, string(output), `<ul>
<li><a href="https://github.com/facundoolano/feedi">feedi</a></li>
<li><a href="https://github.com/facundoolano/blorg">blorg</a></li>
</ul>`)
} }
// ------ HELPERS -------- // ------ HELPERS --------
func newProject() (string, string, string) { func newProject() (string, string, string, string) {
projectDir, _ := os.MkdirTemp("", "root") projectDir, _ := os.MkdirTemp("", "root")
layoutsDir := filepath.Join(projectDir, "layouts") layoutsDir := filepath.Join(projectDir, "layouts")
srcDir := filepath.Join(projectDir, "src") srcDir := filepath.Join(projectDir, "src")
dataDir := filepath.Join(projectDir, "data")
os.Mkdir(layoutsDir, 0777) os.Mkdir(layoutsDir, 0777)
os.Mkdir(filepath.Join(projectDir, "src"), 0777) os.Mkdir(srcDir, 0777)
os.Mkdir(dataDir, 0777)
return projectDir, layoutsDir, srcDir return projectDir, layoutsDir, srcDir, dataDir
} }
func newFile(dir string, filename string, contents string) *os.File { func newFile(dir string, filename string, contents string) *os.File {
path := filepath.Join(dir, filename) path := filepath.Join(dir, filename)
file, _ := os.Create(path) file, err := os.Create(path)
if err != nil {
panic(err)
}
file.WriteString(contents) file.WriteString(contents)
return file return file
} }