2020-09-22 20:42:14 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-04-21 18:03:41 +00:00
|
|
|
"embed"
|
2021-04-11 20:00:29 +00:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
2021-04-11 21:50:18 +00:00
|
|
|
"io"
|
|
|
|
"io/fs"
|
2020-09-22 20:42:14 +00:00
|
|
|
"log"
|
2021-04-11 21:50:18 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2020-09-28 23:54:48 +00:00
|
|
|
)
|
|
|
|
|
2020-09-22 20:42:14 +00:00
|
|
|
func main() {
|
2021-04-20 20:00:39 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-06 12:59:03 +00:00
|
|
|
fmt.Println("usage: kiln <build | new> args...")
|
2021-04-20 20:00:39 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func build() {
|
2021-04-11 20:00:29 +00:00
|
|
|
var (
|
2021-04-20 20:00:39 +00:00
|
|
|
config string
|
2021-04-11 20:00:29 +00:00
|
|
|
)
|
|
|
|
|
2021-04-20 20:12:52 +00:00
|
|
|
flags := flag.NewFlagSet("kiln build", flag.ExitOnError)
|
|
|
|
flags.StringVar(&config, "c", "config.toml", "the configuration file to use")
|
|
|
|
flags.Parse(os.Args[2:])
|
2020-09-22 20:42:14 +00:00
|
|
|
|
2021-05-14 04:17:10 +00:00
|
|
|
site, err := LoadSite(config)
|
2021-03-20 06:02:36 +00:00
|
|
|
if err != nil {
|
2021-09-03 04:22:07 +00:00
|
|
|
log.Fatalf("ERROR: %v", err)
|
2020-11-20 17:07:38 +00:00
|
|
|
}
|
2021-05-09 23:28:09 +00:00
|
|
|
|
2021-05-14 04:17:10 +00:00
|
|
|
if err := site.run(); err != nil {
|
2021-09-03 04:22:07 +00:00
|
|
|
log.Fatalf("ERROR: %v", err)
|
2021-04-11 20:00:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-14 04:17:10 +00:00
|
|
|
func (site *Site) run() error {
|
|
|
|
for _, task := range site.Tasks {
|
|
|
|
err := site.runTask(task)
|
2021-04-11 20:00:29 +00:00
|
|
|
if err != nil {
|
2021-03-21 03:17:58 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-02-28 02:53:16 +00:00
|
|
|
}
|
2021-04-11 20:00:29 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-02-28 02:53:16 +00:00
|
|
|
|
2021-05-14 04:17:10 +00:00
|
|
|
func (s *Site) runTask(task *Task) error {
|
2021-04-21 01:28:29 +00:00
|
|
|
// Read content
|
2022-02-09 18:18:11 +00:00
|
|
|
s.Root = &Page{Path: "/", FilePath: ".", URL: task.URL + "/"}
|
2022-02-09 17:25:39 +00:00
|
|
|
if err := s.Root.read("content", task, s); err != nil {
|
2021-04-11 20:00:29 +00:00
|
|
|
return err
|
|
|
|
}
|
2022-02-09 17:25:39 +00:00
|
|
|
s.Root.sort()
|
2021-04-21 01:28:29 +00:00
|
|
|
// Process content
|
2022-02-09 17:25:39 +00:00
|
|
|
if err := s.Root.process(s, task); err != nil {
|
2021-04-11 20:00:29 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Write content
|
2022-02-09 17:25:39 +00:00
|
|
|
if err := s.Root.write(task.OutputDir, task); err != nil {
|
2021-04-11 20:00:29 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-04-11 21:50:18 +00:00
|
|
|
// Copy static files
|
2021-04-11 22:42:55 +00:00
|
|
|
if task.StaticDir != "" {
|
|
|
|
err := copyAll(task.StaticDir, task.OutputDir)
|
2021-04-11 21:50:18 +00:00
|
|
|
if err != nil {
|
2022-09-24 15:31:42 +00:00
|
|
|
return fmt.Errorf("failed to copy static content: %w", err)
|
2021-04-11 21:50:18 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-22 20:42:14 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-04-11 21:50:18 +00:00
|
|
|
|
|
|
|
func copyAll(srcDir, dstDir string) error {
|
|
|
|
return filepath.Walk(srcDir, func(path string, info fs.FileInfo, err error) error {
|
2021-08-25 11:52:39 +00:00
|
|
|
if err != nil {
|
2022-09-24 15:31:42 +00:00
|
|
|
if path == srcDir && info == nil {
|
|
|
|
// The source directory doesn't exist
|
|
|
|
return nil
|
|
|
|
}
|
2021-08-25 11:52:39 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-04-11 21:50:18 +00:00
|
|
|
if info.IsDir() {
|
|
|
|
// Do nothing
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
src, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer src.Close()
|
|
|
|
|
2021-11-25 16:43:56 +00:00
|
|
|
sinfo, err := src.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
mode := sinfo.Mode()
|
|
|
|
|
2021-04-11 21:50:18 +00:00
|
|
|
dstPath := filepath.Join(dstDir, strings.TrimPrefix(path, srcDir))
|
2021-04-20 21:50:20 +00:00
|
|
|
os.MkdirAll(filepath.Dir(dstPath), 0755)
|
2021-11-25 16:43:56 +00:00
|
|
|
dst, err := os.OpenFile(dstPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, mode)
|
2021-04-11 21:50:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer dst.Close()
|
|
|
|
|
|
|
|
if _, err := io.Copy(dst, src); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
2021-04-20 20:00:39 +00:00
|
|
|
|
2021-05-10 19:03:02 +00:00
|
|
|
//go:embed templates/_default config.toml
|
2021-04-21 18:03:41 +00:00
|
|
|
var builtin embed.FS
|
|
|
|
|
2021-04-20 20:00:39 +00:00
|
|
|
func newSite(name string) {
|
2022-02-09 17:36:59 +00:00
|
|
|
name = filepath.Clean(name)
|
2021-04-20 20:00:39 +00:00
|
|
|
os.Mkdir(name, 0755)
|
2022-02-09 17:36:59 +00:00
|
|
|
os.Mkdir(filepath.Join(name, "content"), 0755)
|
|
|
|
os.Mkdir(filepath.Join(name, "templates"), 0755)
|
|
|
|
os.Mkdir(filepath.Join(name, "templates", "_default"), 0755)
|
|
|
|
os.Mkdir(filepath.Join(name, "static"), 0755)
|
|
|
|
os.Mkdir(filepath.Join(name, "public"), 0755)
|
2021-04-20 20:00:39 +00:00
|
|
|
|
|
|
|
config, _ := builtin.ReadFile("config.toml")
|
2022-02-09 17:36:59 +00:00
|
|
|
os.WriteFile(filepath.Join(name, "config.toml"), config, 0644)
|
2021-04-20 20:00:39 +00:00
|
|
|
|
2021-05-17 16:55:15 +00:00
|
|
|
index := []byte("---\ntitle: Hello, world!\n---\n")
|
2022-02-09 17:36:59 +00:00
|
|
|
os.WriteFile(filepath.Join(name, "content", "_index.gmi"), index, 0644)
|
2021-04-21 18:03:41 +00:00
|
|
|
|
|
|
|
templates := []string{"atom.xml", "index.gmi", "page.gmi"}
|
|
|
|
for _, template := range templates {
|
2022-02-09 17:36:59 +00:00
|
|
|
b, _ := builtin.ReadFile(filepath.Join("templates", "_default", template))
|
|
|
|
os.WriteFile(filepath.Join(name, "templates", "_default", template), b, 0644)
|
2021-04-21 18:03:41 +00:00
|
|
|
}
|
2021-04-20 20:00:39 +00:00
|
|
|
}
|