mirror of
https://git.sr.ht/~adnano/kiln
synced 2024-10-30 01:13:08 +00:00
Implement frontmatter and site configuration
This commit is contained in:
parent
7b6efd6fb8
commit
99e1906d90
5
go.mod
5
go.mod
|
@ -2,4 +2,7 @@ module kiln
|
||||||
|
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require git.sr.ht/~adnano/go-gemini v0.1.4
|
require (
|
||||||
|
git.sr.ht/~adnano/go-gemini v0.1.8
|
||||||
|
git.sr.ht/~adnano/go-ini v0.0.0-20201014024959-cc89f6531f0e
|
||||||
|
)
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -1,2 +1,4 @@
|
||||||
git.sr.ht/~adnano/go-gemini v0.1.4 h1:va3yFDqPQHwcE6AxaP1gBkPlOkSeLXJJqdTTjQzBppY=
|
git.sr.ht/~adnano/go-gemini v0.1.8 h1:93DxDNXB0bjnfDhZewf+QsEopfuOMh/I4v7ujoJ6WIs=
|
||||||
git.sr.ht/~adnano/go-gemini v0.1.4/go.mod h1:If1VxEWcZDrRt5FeAFnGTcM2Ud1E3BXs3VJ5rnZWKq0=
|
git.sr.ht/~adnano/go-gemini v0.1.8/go.mod h1:If1VxEWcZDrRt5FeAFnGTcM2Ud1E3BXs3VJ5rnZWKq0=
|
||||||
|
git.sr.ht/~adnano/go-ini v0.0.0-20201014024959-cc89f6531f0e h1:NRVtAaE3jvBKkwX/x7/yGeQKe8Agj13VDoKKOEE04aA=
|
||||||
|
git.sr.ht/~adnano/go-ini v0.0.0-20201014024959-cc89f6531f0e/go.mod h1:eysIkA6b8oivxACZfyG75+wlq6BW6t5qPVnx8IcFYlE=
|
||||||
|
|
100
main.go
100
main.go
|
@ -3,17 +3,20 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.sr.ht/~adnano/go-gemini"
|
"git.sr.ht/~adnano/go-gemini"
|
||||||
|
"git.sr.ht/~adnano/go-ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -35,25 +38,46 @@ var cfg struct {
|
||||||
url string // site URL
|
url string // site URL
|
||||||
toAtom bool // output Atom
|
toAtom bool // output Atom
|
||||||
toHTML bool // output HTML
|
toHTML bool // output HTML
|
||||||
serveSite bool // serve the site
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
flag.StringVar(&cfg.title, "title", "", "site title")
|
|
||||||
flag.StringVar(&cfg.url, "url", "", "site URL")
|
|
||||||
flag.BoolVar(&cfg.toAtom, "atom", false, "output Atom feed")
|
|
||||||
flag.BoolVar(&cfg.toHTML, "html", false, "output HTML")
|
|
||||||
flag.BoolVar(&cfg.serveSite, "serve", false, "serve the site")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Try to read config file
|
||||||
|
if f, err := os.Open("config.ini"); err == nil {
|
||||||
|
ini.Parse(f, func(section, key, value string) {
|
||||||
|
if section == "" {
|
||||||
|
switch key {
|
||||||
|
case "title":
|
||||||
|
cfg.title = value
|
||||||
|
case "url":
|
||||||
|
cfg.url = value
|
||||||
|
case "atom":
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cfg.toAtom = b
|
||||||
|
case "html":
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cfg.toHTML = b
|
||||||
|
case "serve":
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if err := run(); err != nil {
|
if err := run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if cfg.serveSite {
|
|
||||||
serve()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// site metadata passed to templates
|
// site metadata passed to templates
|
||||||
|
@ -150,14 +174,6 @@ func run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// serve the site
|
|
||||||
func serve() error {
|
|
||||||
var server gemini.Server
|
|
||||||
server.Certificates.Load("/var/lib/gemini/certs")
|
|
||||||
server.Register("localhost", gemini.FileServer(gemini.Dir("dst")))
|
|
||||||
return server.ListenAndServe()
|
|
||||||
}
|
|
||||||
|
|
||||||
// write writes the contents of the Index to the provided destination directory.
|
// write writes the contents of the Index to the provided destination directory.
|
||||||
func write(dir *Dir, dstDir string, format outputFormat) error {
|
func write(dir *Dir, dstDir string, format outputFormat) error {
|
||||||
// Empty the destination directory
|
// Empty the destination directory
|
||||||
|
@ -249,16 +265,42 @@ func (p *Page) Content() string {
|
||||||
// Regexp to parse title from Gemini files
|
// Regexp to parse title from Gemini files
|
||||||
var titleRE = regexp.MustCompile("^# ?([^#\r\n]+)\r?\n?\r?\n?")
|
var titleRE = regexp.MustCompile("^# ?([^#\r\n]+)\r?\n?\r?\n?")
|
||||||
|
|
||||||
|
// Regexp to parse frontmatter from Gemini files
|
||||||
|
var frontmatterRE = regexp.MustCompile("---\r?\n(?s)(.*)(?-s)---\r?\n?")
|
||||||
|
|
||||||
// NewPage returns a new Page with the given path and content.
|
// NewPage returns a new Page with the given path and content.
|
||||||
func NewPage(path string, content []byte) *Page {
|
func NewPage(path string, content []byte) *Page {
|
||||||
|
var page Page
|
||||||
|
|
||||||
|
// Try to parse frontmatter
|
||||||
|
if submatches := frontmatterRE.FindSubmatch(content); submatches != nil {
|
||||||
|
ini.Parse(bytes.NewReader(submatches[1]), func(section, key, value string) {
|
||||||
|
if section == "" {
|
||||||
|
switch key {
|
||||||
|
case "title":
|
||||||
|
page.Title = value
|
||||||
|
case "date":
|
||||||
|
date, err := time.Parse("2006-01-02", value)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
page.Date = date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Preserve unrecognized keys
|
||||||
|
|
||||||
|
})
|
||||||
|
fmt.Println(string(submatches[1]))
|
||||||
|
content = content[len(submatches[0]):]
|
||||||
|
} else {
|
||||||
// Try to parse the date from the page filename
|
// Try to parse the date from the page filename
|
||||||
var date time.Time
|
|
||||||
const layout = "2006-01-02"
|
const layout = "2006-01-02"
|
||||||
base := filepath.Base(path)
|
base := filepath.Base(path)
|
||||||
if len(base) >= len(layout) {
|
if len(base) >= len(layout) {
|
||||||
dateStr := base[:len(layout)]
|
dateStr := base[:len(layout)]
|
||||||
if time, err := time.Parse(layout, dateStr); err == nil {
|
if time, err := time.Parse(layout, dateStr); err == nil {
|
||||||
date = time
|
page.Date = time
|
||||||
}
|
}
|
||||||
// Remove the date from the path
|
// Remove the date from the path
|
||||||
base = base[len(layout):]
|
base = base[len(layout):]
|
||||||
|
@ -278,20 +320,16 @@ func NewPage(path string, content []byte) *Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to parse the title from the contents
|
// Try to parse the title from the contents
|
||||||
var title string
|
|
||||||
if submatches := titleRE.FindSubmatch(content); submatches != nil {
|
if submatches := titleRE.FindSubmatch(content); submatches != nil {
|
||||||
title = string(submatches[1])
|
page.Title = string(submatches[1])
|
||||||
// Remove the title from the contents
|
// Remove the title from the contents
|
||||||
content = content[len(submatches[0]):]
|
content = content[len(submatches[0]):]
|
||||||
}
|
}
|
||||||
|
|
||||||
permalink := strings.TrimSuffix(path, ".gmi")
|
|
||||||
return &Page{
|
|
||||||
Permalink: "/" + permalink + "/",
|
|
||||||
Title: title,
|
|
||||||
Date: date,
|
|
||||||
content: content,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
page.Permalink = "/" + strings.TrimSuffix(path, ".gmi") + "/"
|
||||||
|
page.content = content
|
||||||
|
return &page
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dir represents a directory.
|
// Dir represents a directory.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
// TODO: Use go:embed
|
||||||
|
|
||||||
// Default atom feed template
|
// Default atom feed template
|
||||||
const atom_xml = `<?xml version="1.0" encoding="utf-8"?>
|
const atom_xml = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
|
Loading…
Reference in a new issue