wombat/site/site.go
2023-05-03 19:05:44 +02:00

164 lines
3.9 KiB
Go

package site
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"text/template"
goutil "git.gutmet.org/goutil.git/misc"
. "git.gutmet.org/wombat.git/templatestructures"
)
type metadata struct {
explicit explicitMetadata
subpages []string
}
type explicitMetadata struct {
title string
description string
}
func (m *metadata) getSubpages() []Subpage {
if len(m.subpages) == 0 {
return nil
}
ret := make([]Subpage, 0)
for _, path := range m.subpages {
emd := getExplicitMetadata(path)
if len(emd.title) > 0 && len(emd.description) > 0 {
subpage := Subpage{emd.title, emd.description, path}
ret = append(ret, subpage)
}
}
sort.Slice(ret, func(i, j int) bool { return strings.ToUpper(ret[i].Title) < strings.ToUpper(ret[j].Title) })
return ret
}
func metapath(htmlfile string) string {
if !strings.HasPrefix(htmlfile, "stage1") {
htmlfile = filepath.Join("stage1", htmlfile)
}
return goutil.TrimExt(htmlfile) + ".desc"
}
func getExplicitMetadata(htmlfile string) explicitMetadata {
metapath := metapath(htmlfile)
ret := explicitMetadata{}
f, err := os.Open(metapath)
if err == nil {
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
text := scanner.Text()
if strings.HasPrefix(text, "title:") {
ret.title = strings.Trim(strings.TrimPrefix(text, "title:"), "\" ")
} else if strings.HasPrefix(text, "description:") {
ret.description = strings.TrimSpace(strings.TrimPrefix(text, "description:"))
}
}
} else {
fmt.Fprintln(os.Stderr, err)
}
return ret
}
func isHTML(file os.FileInfo) bool {
return isHTMLFile(file.Name())
}
func isHTMLFile(path string) bool {
return strings.HasSuffix(path, ".html")
}
func hasDescription(path string) bool {
metapath := metapath(path)
if _, err := os.Stat(metapath); os.IsNotExist(err) {
return false
} else {
return true
}
}
func getSubpages(filename string) []string {
ret := []string{}
dirpath := goutil.TrimExt(filename)
if files, err := ioutil.ReadDir(dirpath); err == nil {
for _, file := range files {
if isHTML(file) {
fullpath := strings.TrimPrefix(strings.TrimPrefix(dirpath, "stage1/"), "stage1\\")
ret = append(ret, filepath.Join(fullpath, file.Name()))
}
}
}
return ret
}
func getMetadata(path string) metadata {
ret := metadata{}
ret.explicit = getExplicitMetadata(path)
ret.subpages = getSubpages(path)
return ret
}
func completePage(path string, t *template.Template, style string, script string) {
md := getMetadata(path)
emd := md.explicit
content, _ := goutil.ReadFile(path)
page := Page{}
page.Title = emd.title
page.Style = style
page.Script = script
page.Subpages = md.getSubpages()
page.Description = emd.description
page.Content = content
buf := new(bytes.Buffer)
err := t.Execute(buf, page)
if err != nil {
fmt.Println(err)
}
destination := strings.Replace(path, "stage1", "stage2", 1)
os.Remove(destination) // remove hardlink before writing
goutil.WriteFile(destination, buf.String())
}
func ignore(path string) bool {
var ignorePaths = []string{filepath.Join("stage1", "blog") + string(os.PathSeparator)}
for _, prefix := range ignorePaths {
if strings.HasPrefix(path, prefix) {
return true
}
}
return false
}
func traverse(t *template.Template, style string, script string, path string, info os.FileInfo, err error) error {
if !ignore(path) && isHTMLFile(path) && hasDescription(path) {
completePage(path, t, style, script)
}
return nil
}
func Generate() {
style, err := goutil.ReadFile("style.css")
script, err2 := goutil.ReadFile("script.js")
templateString, err3 := goutil.ReadFile("template")
t := template.Must(template.New("page").Parse(templateString))
traverseFunc := func(path string, info os.FileInfo, err error) error {
return traverse(t, style, script, path, info, err)
}
if err == nil && err2 == nil && err3 == nil {
filepath.Walk("stage1", traverseFunc)
} else {
fmt.Println(err)
fmt.Println(err2)
fmt.Println(err3)
}
}