mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-01 00:33:05 +08:00
genblog: Further simplify code.
This commit is contained in:
parent
fa77792ad5
commit
03cb64ea2f
|
@ -4,7 +4,7 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
@ -92,65 +92,40 @@ func (ra *recentArticles) insert(a article) {
|
|||
ra.articles[i] = a
|
||||
}
|
||||
|
||||
func articlesToDots(b *baseDot, as []article) []articleDot {
|
||||
ads := make([]articleDot, len(as))
|
||||
for i, a := range as {
|
||||
ads[i] = articleDot(articleDot{b, a})
|
||||
}
|
||||
return ads
|
||||
}
|
||||
|
||||
// decodeFile decodes the named file in TOML into a pointer.
|
||||
func decodeFile(fname string, v interface{}) {
|
||||
func decodeTOML(fname string, v interface{}) {
|
||||
_, err := toml.DecodeFile(fname, v)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
// readCatetoryConf reads a category configuration file.
|
||||
func readCategoryConf(cat, fname string) *categoryConf {
|
||||
conf := &categoryConf{}
|
||||
decodeFile(fname, conf)
|
||||
return conf
|
||||
func readFile(fname string) string {
|
||||
content, err := ioutil.ReadFile(fname)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return string(content)
|
||||
}
|
||||
|
||||
// readAllAndStat retrieves all content of the named file and its stat.
|
||||
func readAllAndStat(fname string) (string, os.FileInfo) {
|
||||
file, err := os.Open(fname)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
defer file.Close()
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
fi, err := file.Stat()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return string(content), fi
|
||||
}
|
||||
|
||||
func readAll(fname string) string {
|
||||
all, _ := readAllAndStat(fname)
|
||||
return all
|
||||
}
|
||||
|
||||
func catAllInDir(dirname string, fnames []string) string {
|
||||
func catInDir(dirname string, fnames []string) string {
|
||||
var sb strings.Builder
|
||||
for _, fname := range fnames {
|
||||
sb.WriteString(readAll(path.Join(dirname, fname)))
|
||||
sb.WriteString(readFile(filepath.Join(dirname, fname)))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func getArticle(a article, am articleMeta, dir string) article {
|
||||
content, fi := readAllAndStat(path.Join(dir, am.Name+".html"))
|
||||
modTime := fi.ModTime()
|
||||
css := catAllInDir(dir, am.ExtraCSS)
|
||||
js := catAllInDir(dir, am.ExtraJS)
|
||||
fname := filepath.Join(dir, am.Name+".html")
|
||||
content := readFile(fname)
|
||||
fileInfo, err := os.Stat(fname)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
modTime := fileInfo.ModTime()
|
||||
css := catInDir(dir, am.ExtraCSS)
|
||||
js := catInDir(dir, am.ExtraJS)
|
||||
return article{
|
||||
am, a.IsHomepage, a.Category, content, css, js, rfc3339Time(modTime)}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -16,10 +17,18 @@ func main() {
|
|||
log.Fatal("Usage: genblog <src dir> <dst dir>")
|
||||
}
|
||||
srcDir, dstDir := args[0], args[1]
|
||||
srcFile := func(elem ...string) string {
|
||||
elem = append([]string{srcDir}, elem...)
|
||||
return filepath.Join(elem...)
|
||||
}
|
||||
dstFile := func(elem ...string) string {
|
||||
elem = append([]string{dstDir}, elem...)
|
||||
return filepath.Join(elem...)
|
||||
}
|
||||
|
||||
// Read blog configuration.
|
||||
conf := &blogConf{}
|
||||
decodeFile(path.Join(srcDir, "index.toml"), conf)
|
||||
decodeTOML(srcFile("index.toml"), conf)
|
||||
if conf.RootURL == "" {
|
||||
log.Fatal("RootURL must be specified; needed by feed and sitemap")
|
||||
}
|
||||
|
@ -30,8 +39,8 @@ func main() {
|
|||
log.Fatal("BaseCSS must be specified")
|
||||
}
|
||||
|
||||
template := readAll(path.Join(srcDir, conf.Template))
|
||||
baseCSS := catAllInDir(srcDir, conf.BaseCSS)
|
||||
template := readFile(srcFile(conf.Template))
|
||||
baseCSS := catInDir(srcDir, conf.BaseCSS)
|
||||
|
||||
// Initialize templates. They are all initialized from the same source code,
|
||||
// plus a snippet to fix the "content" reference.
|
||||
|
@ -63,7 +72,7 @@ func main() {
|
|||
// Add category index to the sitemap, without "/index.html"
|
||||
allPaths = append(allPaths, name)
|
||||
// Create directory
|
||||
catDir := path.Join(dstDir, name)
|
||||
catDir := dstFile(name)
|
||||
err := os.MkdirAll(catDir, 0755)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -71,7 +80,7 @@ func main() {
|
|||
|
||||
// Generate index
|
||||
cd := &categoryDot{base, name, prelude, articles, css, js}
|
||||
executeToFile(categoryTmpl, cd, path.Join(catDir, "index.html"))
|
||||
executeToFile(categoryTmpl, cd, filepath.Join(catDir, "index.html"))
|
||||
}
|
||||
|
||||
for _, cat := range conf.Categories {
|
||||
|
@ -84,24 +93,24 @@ func main() {
|
|||
continue
|
||||
}
|
||||
|
||||
catConf := readCategoryConf(cat.Name, path.Join(srcDir, cat.Name, "index.toml"))
|
||||
catConf := &categoryConf{}
|
||||
decodeTOML(srcFile(cat.Name, "index.toml"), catConf)
|
||||
|
||||
prelude := ""
|
||||
if catConf.Prelude != "" {
|
||||
prelude = readAll(
|
||||
path.Join(srcDir, cat.Name, catConf.Prelude+".html"))
|
||||
prelude = readFile(srcFile(cat.Name, catConf.Prelude+".html"))
|
||||
}
|
||||
css := catAllInDir(path.Join(srcDir, cat.Name), catConf.ExtraCSS)
|
||||
js := catAllInDir(path.Join(srcDir, cat.Name), catConf.ExtraJS)
|
||||
css := catInDir(srcFile(cat.Name), catConf.ExtraCSS)
|
||||
js := catInDir(srcFile(cat.Name), catConf.ExtraJS)
|
||||
renderCategoryIndex(cat.Name, prelude, css, js, catConf.Articles)
|
||||
|
||||
// Generate articles
|
||||
for _, am := range catConf.Articles {
|
||||
// Add article URL to sitemap.
|
||||
p := path.Join(cat.Name, am.Name+".html")
|
||||
p := filepath.Join(cat.Name, am.Name+".html")
|
||||
allPaths = append(allPaths, p)
|
||||
|
||||
a := getArticle(article{Category: cat.Name}, am, path.Join(srcDir, cat.Name))
|
||||
a := getArticle(article{Category: cat.Name}, am, srcFile(cat.Name))
|
||||
modTime := time.Time(a.LastModified)
|
||||
if modTime.After(lastModified) {
|
||||
lastModified = modTime
|
||||
|
@ -109,7 +118,7 @@ func main() {
|
|||
|
||||
// Generate article page.
|
||||
ad := &articleDot{base, a}
|
||||
executeToFile(articleTmpl, ad, path.Join(dstDir, p))
|
||||
executeToFile(articleTmpl, ad, dstFile(p))
|
||||
|
||||
allArticleMetas = append(allArticleMetas, a.articleMeta)
|
||||
recents.insert(a)
|
||||
|
@ -118,7 +127,9 @@ func main() {
|
|||
|
||||
// Generate "all category"
|
||||
if hasAllCategory {
|
||||
sortArticleMetas(allArticleMetas)
|
||||
sort.Slice(allArticleMetas, func(i, j int) bool {
|
||||
return allArticleMetas[i].Timestamp > allArticleMetas[j].Timestamp
|
||||
})
|
||||
renderCategoryIndex("all", "", "", "", allArticleMetas)
|
||||
}
|
||||
|
||||
|
@ -126,18 +137,15 @@ func main() {
|
|||
// article pages.
|
||||
a := getArticle(article{IsHomepage: true, Category: "homepage"}, conf.Index, srcDir)
|
||||
ad := &articleDot{base, a}
|
||||
executeToFile(homepageTmpl, ad, path.Join(dstDir, "index.html"))
|
||||
executeToFile(homepageTmpl, ad, dstFile("index.html"))
|
||||
|
||||
// Generate feed.
|
||||
feedArticles := recents.articles
|
||||
fd := feedDot{base, feedArticles, rfc3339Time(lastModified)}
|
||||
executeToFile(feedTmpl, fd, path.Join(dstDir, "feed.atom"))
|
||||
executeToFile(feedTmpl, fd, dstFile("feed.atom"))
|
||||
|
||||
// Generate site map.
|
||||
file, err := openForWrite(path.Join(dstDir, "sitemap.txt"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
file := openForWrite(dstFile("sitemap.txt"))
|
||||
defer file.Close()
|
||||
for _, p := range allPaths {
|
||||
fmt.Fprintf(file, "%s/%s\n", conf.RootURL, p)
|
||||
|
|
|
@ -78,17 +78,18 @@ func newTemplate(name, root string, sources ...string) *template.Template {
|
|||
return t
|
||||
}
|
||||
|
||||
func openForWrite(fname string) (*os.File, error) {
|
||||
return os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
}
|
||||
|
||||
func executeToFile(t *template.Template, data interface{}, fname string) {
|
||||
file, err := openForWrite(fname)
|
||||
func openForWrite(fname string) *os.File {
|
||||
file, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
func executeToFile(t *template.Template, data interface{}, fname string) {
|
||||
file := openForWrite(fname)
|
||||
defer file.Close()
|
||||
err = t.Execute(file, data)
|
||||
err := t.Execute(file, data)
|
||||
if err != nil {
|
||||
log.Fatalf("rendering %q: %s", fname, err)
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package main
|
||||
|
||||
import "sort"
|
||||
|
||||
func sortArticleMetas(a []articleMeta) {
|
||||
sort.Slice(a, func(i, j int) bool {
|
||||
return a[i].Timestamp > a[j].Timestamp
|
||||
})
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
Loading…
Reference in New Issue
Block a user