load template data from json, toml, or yaml

because why not, the required modules were already included as dependencies for other things
nothing new in go.mod, just indirect -> direct
This commit is contained in:
Lilian Jónsdóttir 2024-01-23 18:14:15 -08:00
parent e446e6520b
commit 16397fce66
5 changed files with 94 additions and 73 deletions

6
go.mod
View file

@ -3,16 +3,17 @@ module git.burning.moe/celediel/burning.moe
go 1.21.5
require (
github.com/BurntSushi/toml v1.3.2
github.com/charmbracelet/log v0.3.1
github.com/go-chi/chi/v5 v5.0.11
github.com/ilyakaznacheev/cleanenv v1.5.0
github.com/magefile/mage v1.15.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.9.1 // indirect
github.com/charmbracelet/log v0.3.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
@ -23,6 +24,5 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/sys v0.13.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
)

7
go.sum
View file

@ -7,6 +7,8 @@ github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw=
github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
@ -28,14 +30,19 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -2,31 +2,37 @@ package models
import (
"encoding/json"
"errors"
"html/template"
"os"
"strings"
"time"
"github.com/BurntSushi/toml"
"gopkg.in/yaml.v3"
)
const dataDir string = "./templates/data/"
// in order of precedence
var dataExtensions = [4]string{"yml", "yaml", "toml", "json"}
type Link struct {
Href template.URL
Text string
Icon template.URL
Href, Icon template.URL
Text string
}
// TemplateData holds data sent from handlers to templates.
type TemplateData struct {
StringMap map[string]string `json:"stringMap"`
IntMap map[string]int `json:"intMap"`
FloatMap map[string]float32 `json:"floatMap"`
LinkMap map[string][]Link `json:"linkMap"`
Data map[string]interface{} `json:"data"`
CSRFToken string `json:"csrftoken"`
Flash string `json:"flash"`
Warning string `json:"warning"`
Error string `json:"error"`
StringMap map[string]string `json:"StringMap" yaml:"StringMap" toml:"StringMap"`
IntMap map[string]int `json:"IntMap" yaml:"IntMap" toml:"IntMap"`
FloatMap map[string]float32 `json:"FloatMap" yaml:"FloatMap" toml:"FloatMap"`
LinkMap map[string][]Link `json:"LinkMap" yaml:"LinkMap" toml:"LinkMap"`
Data map[string]interface{} `json:"Data" yaml:"Data" toml:"Data"`
CSRFToken string `json:"Csrftoken" yaml:"Csrftoken" toml:"Csrftoken"`
Flash string `json:"Flash" yaml:"Flash" toml:"Flash"`
Warning string `json:"Warning" yaml:"Warning" toml:"Warning"`
Error string `json:"Error" yaml:"Error" toml:"Error"`
}
// makeBasicTemplateData creates a blank TemplateData containing only the
@ -45,19 +51,47 @@ func MakeBasicTemplateData(when time.Time) TemplateData {
// LoadTemplateData loads template data from file. If that
// fails, it returns an empty TemplateData and an error
func LoadTemplateData(page string) (TemplateData, error) {
// TODO: load from something other than JSON
var data *TemplateData
output := dataDir + strings.ReplaceAll(page, "tmpl", "json")
var data TemplateData
output := dataDir + strings.ReplaceAll(page, "tmpl", "")
file, err := os.ReadFile(output)
if err != nil {
return TemplateData{}, err
for _, extension := range dataExtensions {
if info, err := os.Stat(output + extension); err == nil && !info.IsDir() {
data, err = loadFromFile(output, extension)
if err == nil {
// don't try anymore files
return data, nil
}
}
}
err = json.Unmarshal(file, &data)
if err != nil {
return TemplateData{}, err
}
return *data, nil
// couldn't load anything from file
return TemplateData{}, errors.New("Couldn't load data from file")
}
// loadFromFile loads TemplateData from the specified filetype (yaml, toml, or json)
func loadFromFile(filename, filetype string) (TemplateData, error) {
var data TemplateData
file, err := os.ReadFile(filename + filetype)
if err != nil {
return TemplateData{}, err
}
switch filetype {
case "json":
err = json.Unmarshal(file, &data)
if err != nil {
return TemplateData{}, err
}
case "toml":
err = toml.Unmarshal(file, &data)
if err != nil {
return TemplateData{}, err
}
case "yaml":
err = yaml.Unmarshal(file, &data)
if err != nil {
return TemplateData{}, err
}
}
return data, nil
}

View file

@ -1,46 +0,0 @@
{
"StringMap": {
"about": "she/her, 1989, queer anarchist and self-taught, aspiring developer and sysadmin"
},
"LinkMap": {
"Personal": [
{
"href": "https://matrix.to/#/@celediel:burning.moe",
"text": "matrix",
"icon": "tabler:brand-matrix"
},
{
"href": "https://slrpnk.net/u/Celediel",
"text": "lemmy",
"icon": "simple-icons:lemmy"
},
{
"href": "https://git.burning.moe/celediel",
"text": "self-hosted git",
"icon": "mdi:git"
},
{
"href": "https://github.com/celediel",
"text": "github",
"icon": "bi:github"
}
],
"HostedApps": [
{
"href": "https://git.burning.moe/",
"text": "self-hosted git",
"icon": "mdi:git"
},
{
"href": "https://bin.burning.moe/",
"text": "wastebin",
"icon": "fluent:bin-recycle-20-filled"
},
{
"href": "https://gist.burning.moe/",
"text": "gist",
"icon": "carbon:paste"
}
]
}
}

View file

@ -0,0 +1,26 @@
StringMap:
about: she/her, 1989, queer anarchist and self-taught, aspiring developer and sysadmin
LinkMap:
Personal:
- href: https://matrix.to/#/@celediel:burning.moe
text: matrix
icon: tabler:brand-matrix
- href: https://slrpnk.net/u/Celediel
text: lemmy
icon: simple-icons:lemmy
- href: https://git.burning.moe/celediel
text: self-hosted git
icon: mdi:git
- href: https://github.com/celediel
text: github
icon: bi:github
HostedApps:
- href: https://git.burning.moe/
text: self-hosted git
icon: mdi:git
- href: https://bin.burning.moe/
text: wastebin
icon: fluent:bin-recycle-20-filled
- href: https://gist.burning.moe/
text: gist
icon: carbon:paste