kiln/main.go
2021-05-10 00:54:13 -04:00

172 lines
3.3 KiB
Go

package main
import (
"embed"
"flag"
"fmt"
"io"
"io/fs"
"log"
"os"
"path"
"path/filepath"
"strings"
)
var (
Version string
)
func main() {
if len(os.Args) >= 2 {
switch os.Args[1] {
case "build":
build()
return
case "new":
if len(os.Args) < 3 {
fmt.Println("usage: kiln new <path>")
os.Exit(1)
}
newSite(os.Args[2])
return
case "version":
fmt.Println("kiln", Version)
return
}
}
fmt.Println("usage: kiln <build | new | version> args...")
os.Exit(1)
}
func build() {
var (
task string
config string
)
flags := flag.NewFlagSet("kiln build", flag.ExitOnError)
flags.StringVar(&task, "t", "", "the task to run")
flags.StringVar(&config, "c", "config.toml", "the configuration file to use")
flags.Parse(os.Args[2:])
// Load config
cfg, err := LoadConfig(config)
if err != nil {
log.Fatal(err)
}
templateExts := []string{}
for _, task := range cfg.Tasks {
if task.TemplateExt != "" {
templateExts = append(templateExts, task.TemplateExt)
}
}
if err := cfg.templates.Load("templates", templateExts); err != nil {
log.Fatal(err)
}
if err := run(cfg, task); err != nil {
log.Fatal(err)
}
}
func run(cfg *Config, taskName string) error {
if taskName == "" {
return runAll(cfg)
}
task, ok := cfg.Tasks[taskName]
if !ok {
return fmt.Errorf("run task %q: no such task", taskName)
}
return runTask(cfg, task)
}
func runAll(cfg *Config) error {
for _, task := range cfg.Tasks {
err := runTask(cfg, task)
if err != nil {
return err
}
}
return nil
}
func runTask(cfg *Config, task *Task) error {
// Read content
dir := NewDir("")
if err := dir.Read("content", task); err != nil {
return err
}
dir.sort()
// Process content
if err := dir.Process(cfg, task); err != nil {
return err
}
// Write content
if err := dir.Write(task.OutputDir, task); err != nil {
return err
}
// Copy static files
if task.StaticDir != "" {
err := copyAll(task.StaticDir, task.OutputDir)
if err != nil {
return err
}
}
return nil
}
func copyAll(srcDir, dstDir string) error {
return filepath.Walk(srcDir, func(path string, info fs.FileInfo, err error) error {
if info.IsDir() {
// Do nothing
return nil
}
src, err := os.Open(path)
if err != nil {
return err
}
defer src.Close()
dstPath := filepath.Join(dstDir, strings.TrimPrefix(path, srcDir))
os.MkdirAll(filepath.Dir(dstPath), 0755)
dst, err := os.Create(dstPath)
if err != nil {
return err
}
defer dst.Close()
if _, err := io.Copy(dst, src); err != nil {
return err
}
return nil
})
}
//go:embed templates config.toml
var builtin embed.FS
func newSite(name string) {
name = path.Clean(name)
os.Mkdir(name, 0755)
os.Mkdir(path.Join(name, "content"), 0755)
os.Mkdir(path.Join(name, "templates"), 0755)
os.Mkdir(path.Join(name, "templates/_default"), 0755)
os.Mkdir(path.Join(name, "static"), 0755)
config, _ := builtin.ReadFile("config.toml")
os.WriteFile(path.Join(name, "config.toml"), config, 0644)
index := []byte("# Hello, world!\n")
os.WriteFile(path.Join(name, "content/index.gmi"), index, 0644)
templates := []string{"atom.xml", "index.gmi", "page.gmi"}
for _, template := range templates {
b, _ := builtin.ReadFile(path.Join("templates", template))
os.WriteFile(path.Join(name, "templates/_default", template), b, 0644)
}
}