1
0
mirror of https://git.sr.ht/~adnano/kiln synced 2024-11-08 14:19:20 +01:00

Implement support for preprocess command

This commit is contained in:
adnano 2021-04-20 21:28:29 -04:00
parent 91d9dc09fa
commit 20efed1e9a
3 changed files with 69 additions and 90 deletions

@ -1,11 +1,8 @@
package main
import (
"log"
"os"
"os/exec"
"path"
"strings"
"text/template"
"github.com/BurntSushi/toml"
@ -25,28 +22,14 @@ type Task struct {
InputExt string `toml:"input_ext"` // input file extension
OutputExt string `toml:"output_ext"` // output file extension
TemplateExt string `toml:"template_ext"` // template file extension
PreProcess string `toml:"preprocess"` // preprocess command
PostProcess string `toml:"postprocess"` // postprocess command
StaticDir string `toml:"static_dir"` // static file directory
OutputDir string `toml:"output_dir"` // output directory
}
func (t Task) Format(p *Page) (string, []byte) {
path := path.Join(p.Path, "index"+t.OutputExt)
// Run a custom command.
if t.PostProcess != "" {
split := strings.Split(t.PostProcess, " ")
cmd := exec.Command(split[0], split[1:]...)
cmd.Stdin = strings.NewReader(p.Content)
cmd.Stderr = os.Stderr
output, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
return path, output
}
return path, []byte(p.Content)
func (t Task) OutputPath(pagePath string) string {
return path.Join(pagePath, "index"+t.OutputExt)
}
// LoadConfig loads the configuration from the provided path.

123
dir.go

@ -2,8 +2,11 @@ package main
import (
"bytes"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
pathpkg "path"
"sort"
"strings"
@ -19,10 +22,6 @@ type Dir struct {
Dirs []*Dir // Subdirectories.
index *Page // The index page.
feed []byte // Atom feed.
inputExt string // input file extension
outputExt string // output file extension
templateExt string // template file extension
}
// NewDir returns a new Dir with the given path.
@ -37,8 +36,12 @@ func NewDir(path string) *Dir {
}
}
// read reads from a directory and indexes the files and directories within it.
func (d *Dir) read(srcDir string, path string) error {
// Read reads from a directory and indexes the files and directories within it.
func (d *Dir) Read(srcDir string, task *Task) error {
return d.read(srcDir, "", task)
}
func (d *Dir) read(srcDir, path string, task *Task) error {
entries, err := ioutil.ReadDir(pathpkg.Join(srcDir, path))
if err != nil {
return err
@ -53,51 +56,51 @@ func (d *Dir) read(srcDir string, path string) error {
if entry.IsDir() {
// Gather directory data
dir := NewDir(path)
dir.inputExt = d.inputExt
dir.outputExt = d.outputExt
dir.templateExt = d.templateExt
if err := dir.read(srcDir, path); err != nil {
if err := dir.read(srcDir, path, task); err != nil {
return err
}
d.Dirs = append(d.Dirs, dir)
} else {
} else if ext := pathpkg.Ext(name); ext == task.InputExt {
srcPath := pathpkg.Join(srcDir, path)
content, err := ioutil.ReadFile(srcPath)
if err != nil {
return err
}
if ext := pathpkg.Ext(name); ext == d.inputExt {
// Gather page data
if strings.TrimSuffix(name, ext) == "index" {
d.index = NewPage(d.Path, content)
d.Title = d.index.Title
d.Content = d.index.Content
} else {
d.Pages = append(d.Pages, NewPage(path, content))
}
if cmd := task.PreProcess; cmd != "" {
content = RunProcessCmd(cmd, bytes.NewReader(content))
}
// Gather page data
if strings.TrimSuffix(name, ext) == "index" {
d.index = NewPage(d.Path, content)
d.Title = d.index.Title
d.Content = d.index.Content
} else {
d.Pages = append(d.Pages, NewPage(path, content))
}
}
}
return nil
}
// manipulate processes and manipulates the directory's contents.
func (d *Dir) manipulate(cfg *Config) error {
if d.templateExt != "" {
// Process processes the directory's contents.
func (d *Dir) Process(cfg *Config, task *Task) error {
if task.TemplateExt != "" {
// Create index
if d.index != nil {
var b strings.Builder
tmpl := cfg.Templates.FindTemplate(d.Path, "index"+d.templateExt)
tmpl := cfg.Templates.FindTemplate(d.Path, "index"+task.TemplateExt)
if err := tmpl.Execute(&b, d); err != nil {
return err
}
d.index.Content = b.String()
}
// Manipulate pages
// Process pages
for i := range d.Pages {
var b strings.Builder
tmpl := cfg.Templates.FindTemplate(d.Path, "page"+d.templateExt)
tmpl := cfg.Templates.FindTemplate(d.Path, "page"+task.TemplateExt)
if err := tmpl.Execute(&b, d.Pages[i]); err != nil {
return err
}
@ -129,22 +132,17 @@ func (d *Dir) manipulate(cfg *Config) error {
d.feed = b.Bytes()
}
// Manipulate subdirectories
// Process subdirectories
for _, d := range d.Dirs {
if err := d.manipulate(cfg); err != nil {
if err := d.Process(cfg, task); err != nil {
return err
}
}
return nil
}
// Format represents an output format.
type Format interface {
Format(*Page) (path string, content []byte)
}
// write writes the Dir to the provided destination path.
func (d *Dir) write(dstDir string, format Format) error {
// Write writes the directory's contents to the provided destination path.
func (d *Dir) Write(dstDir string, task *Task) error {
// Create the directory
dirPath := pathpkg.Join(dstDir, d.Path)
if err := os.MkdirAll(dirPath, 0755); err != nil {
@ -152,31 +150,23 @@ func (d *Dir) write(dstDir string, format Format) error {
}
// Write pages
for _, page := range d.Pages {
path, content := format.Format(page)
dstPath := pathpkg.Join(dstDir, path)
dir := pathpkg.Dir(dstPath)
os.MkdirAll(dir, 0755)
f, err := os.Create(dstPath)
if err != nil {
return err
}
if _, err := f.Write(content); err != nil {
return err
}
}
// Write the index file
pages := d.Pages
if d.index != nil {
path, content := format.Format(d.index)
pages = append(pages, d.index)
}
for _, page := range pages {
path := task.OutputPath(page.Path)
var content []byte
if cmd := task.PostProcess; cmd != "" {
content = RunProcessCmd(cmd, strings.NewReader(page.Content))
} else {
content = []byte(page.Content)
}
dstPath := pathpkg.Join(dstDir, path)
dir := pathpkg.Dir(dstPath)
os.MkdirAll(dir, 0755)
f, err := os.Create(dstPath)
if err != nil {
return err
}
if _, err := f.Write(content); err != nil {
if err := os.WriteFile(dstPath, content, 0644); err != nil {
return err
}
}
@ -186,18 +176,14 @@ func (d *Dir) write(dstDir string, format Format) error {
const path = "atom.xml"
dstPath := pathpkg.Join(dstDir, path)
os.MkdirAll(dstDir, 0755)
f, err := os.Create(dstPath)
if err != nil {
return err
}
if _, err := f.Write(d.feed); err != nil {
if err := os.WriteFile(dstPath, d.feed, 0644); err != nil {
return err
}
}
// Write subdirectories
for _, dir := range d.Dirs {
dir.write(dstDir, format)
dir.Write(dstDir, task)
}
return nil
}
@ -212,3 +198,16 @@ func (d *Dir) sort() {
d.sort()
}
}
// RunProcessCmd runs a process command.
func RunProcessCmd(command string, input io.Reader) []byte {
split := strings.Split(command, " ")
cmd := exec.Command(split[0], split[1:]...)
cmd.Stdin = input
cmd.Stderr = os.Stderr
output, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
return output
}

13
main.go

@ -86,21 +86,18 @@ func runAll(cfg *Config) error {
}
func runTask(cfg *Config, task *Task) error {
// Load content
// Read content
dir := NewDir("")
dir.inputExt = task.InputExt
dir.outputExt = task.OutputExt
dir.templateExt = task.TemplateExt
if err := dir.read("content", ""); err != nil {
if err := dir.Read("content", task); err != nil {
return err
}
dir.sort()
// Manipulate content
if err := dir.manipulate(cfg); err != nil {
// Process content
if err := dir.Process(cfg, task); err != nil {
return err
}
// Write content
if err := dir.write(task.OutputDir, task); err != nil {
if err := dir.Write(task.OutputDir, task); err != nil {
return err
}
// Copy static files