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