initial commit, laying some groundwork
This commit is contained in:
commit
af7a4dceb9
|
@ -0,0 +1,2 @@
|
|||
go.sum
|
||||
sitegenerator
|
|
@ -0,0 +1,5 @@
|
|||
module tildegit.org/nihilazo/sitegenerator
|
||||
|
||||
go 1.15
|
||||
|
||||
require tildegit.org/nihilazo/go-gemtext v0.0.0-20201114202124-890be6eb3742
|
|
@ -0,0 +1,170 @@
|
|||
// A website generator tool
|
||||
package main
|
||||
|
||||
import (
|
||||
"tildegit.org/nihilazo/go-gemtext"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// TODO replace these hardcoded paths with config
|
||||
var root string = "/mnt/term/home/nico/website/wiki"
|
||||
var geminiPrefix string = "gemini://breadpunk.club/~bagel"
|
||||
var htmlPrefix string = "https://itwont.work"
|
||||
var geminiOutputDir string = filepath.Join(root, "public_gemini")
|
||||
var htmlOutputDir string = filepath.Join(root, "public_html")
|
||||
var inputDir string = filepath.Join(root, "content")
|
||||
var tagFile string = filepath.Join(root, "tags.json")
|
||||
|
||||
type filePathInfo struct {
|
||||
Path string
|
||||
New bool // True if the file is new
|
||||
}
|
||||
|
||||
type pageInfo struct {
|
||||
Path string
|
||||
Title string
|
||||
}
|
||||
|
||||
// RemoveIndex is a reslicing function.
|
||||
func RemoveIndex(s []pageInfo, index int) []pageInfo {
|
||||
return append(s[:index], s[index+1:]...)
|
||||
}
|
||||
|
||||
var tagData map[string][]pageInfo = make(map[string][]pageInfo)
|
||||
|
||||
var files []filePathInfo // Files to process (those that are new or have been edited)
|
||||
|
||||
func copy(src, dst string) (int64, error) {
|
||||
sourceFileStat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if !sourceFileStat.Mode().IsRegular() {
|
||||
return 0, fmt.Errorf("%s is not a regular file", src)
|
||||
}
|
||||
|
||||
source, err := os.Open(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
destination, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer destination.Close()
|
||||
nBytes, err := io.Copy(destination, source)
|
||||
return nBytes, err
|
||||
}
|
||||
|
||||
func processPage(f filePathInfo) error {
|
||||
|
||||
// Delete any existing tag references to this file
|
||||
if filepath.Ext(f.Path) == ".gmi" {
|
||||
for i,d := range tagData { // For each tag in tagdata
|
||||
if len(d) != 0 {
|
||||
for j, _ := range d { // for each file in the tag
|
||||
if files[j].Path == f.Path {
|
||||
tagData[i] = RemoveIndex(d,j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Open the file and parse the gemtext
|
||||
data, err := ioutil.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parse, err := gemtext.ParsePage(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO get tag data from files
|
||||
// TODO render and write HTML and gemini
|
||||
} else if filepath.Ext(f.Path) == ".tpl" {
|
||||
// TODO handle template files
|
||||
} else { // Non-gemtext files
|
||||
rel, err := filepath.Rel(inputDir, f.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(f.Path, filepath.Join(htmlOutputDir, rel))
|
||||
copy(f.Path, filepath.Join(geminiOutputDir, rel))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// walkInputDir is called when walking the input directory, finds what files are new or have been edited, adds them to files
|
||||
func walkInputDir(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
rel, err := filepath.Rel(inputDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outPath := filepath.Join(geminiOutputDir, rel)
|
||||
outFileInfo, err := os.Stat(outPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
files = append(files, filePathInfo{Path: path, New: true})
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if info.ModTime().After(outFileInfo.ModTime()) {
|
||||
files = append(files, filePathInfo{Path: path})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func main() {
|
||||
loadingJson := true
|
||||
if _, err := os.Stat(tagFile); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
loadingJson = false
|
||||
fmt.Println("Not loading tags file, it doesn't exist yet")
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
tagFileData, err := ioutil.ReadFile(tagFile)
|
||||
if loadingJson {
|
||||
err = json.Unmarshal([]byte(tagFileData), &tagData)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = filepath.Walk(inputDir, walkInputDir) // walks the tree, creates the files slice and updates tagData
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
for _, file := range files {
|
||||
err := processPage(file) // Process all the updated files.
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
// TODO tag pages
|
||||
json, err := json.Marshal(tagData)
|
||||
err = ioutil.WriteFile(tagFile, json, 0644)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
Reference in New Issue