static web generator written in Go
Files | Log | Commits | Refs | README
Size: 2616 bytes
/* mist - minimal static site generator */
/* see LICENSE for copyright and license details */
package main
import (
"flag"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/gomarkdown/markdown"
)
type Page struct {
Title string
Content string
Nav []string
}
func die(err error) {
if err != nil {
log.Fatal(err)
}
}
func getTitle(path string) string {
name := filepath.Base(path)
return strings.TrimSuffix(name, ".md")
}
func mkNav(dir string) []string {
files, err := os.ReadDir(dir)
die(err)
var nav []string
for _, f := range files {
if strings.HasSuffix(f.Name(), ".md") && f.Name() != "index.md" {
name := strings.TrimSuffix(f.Name(), ".md")
nav = append(nav, name)
}
}
return nav
}
func copy(src, dst string) {
in, err := os.Open(src)
die(err)
defer in.Close()
out, err := os.Create(dst)
die(err)
defer out.Close()
io.Copy(out, in)
}
func process(src, dst, tpl string) {
os.MkdirAll(dst, 0755)
copy("style.css", filepath.Join(dst, "style.css"))
copy(tpl, filepath.Join(dst, "template.html"))
files, err := os.ReadDir(src)
die(err)
t, err := template.ParseFiles(tpl)
die(err)
nav := mkNav(src)
for _, f := range files {
if strings.HasSuffix(f.Name(), ".md") {
md, err := os.ReadFile(filepath.Join(src, f.Name()))
die(err)
page := Page{
Title: getTitle(filepath.Join(src, f.Name())),
Content: string(markdown.ToHTML(md, nil, nil)),
Nav: nav,
}
name := strings.TrimSuffix(f.Name(), ".md")
if name == "index" {
name = "index.html"
} else {
name += ".html"
}
out, err := os.Create(filepath.Join(dst, name))
die(err)
die(t.Execute(out, page))
out.Close()
} else {
copy(filepath.Join(src, f.Name()), filepath.Join(dst, f.Name()))
}
}
}
func serve(dir, port string) {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
if path == "/" {
path = "/index.html"
} else if !strings.HasSuffix(path, ".html") && !strings.Contains(path, ".") {
if _, err := os.Stat(filepath.Join(dir, path[1:]+".html")); err == nil {
path += ".html"
}
}
http.ServeFile(w, r, filepath.Join(dir, path[1:]))
})
log.Printf("serving %s on :%s", dir, port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
func main() {
src := flag.String("i", ".", "input dir")
dst := flag.String("o", "out", "output dir")
tpl := flag.String("t", "page.tmpl", "template")
port := flag.String("s", "", "serve on port")
flag.Parse()
if *port != "" {
serve(*dst, *port)
} else {
process(*src, *dst, *tpl)
}
}