Compare commits

..

No commits in common. "3dbd5a86e2ac4dffda03696dad4a30c1263f7f92" and "64b40c3d82eeff06dd40265cb9d9d714cd999428" have entirely different histories.

14 changed files with 68 additions and 237 deletions

View file

@ -3,14 +3,11 @@
Code for the [burning.moe](https://burning.moe) homepage Code for the [burning.moe](https://burning.moe) homepage
## technologies used ## technologies used
- written in [go](https://go.dev) using: - [go](https://go.dev)
- [chi](https://github.com/go-chi/chi) - [chi](https://github.com/go-chi/chi)
- [cleanenv](https://github.com/ilyakaznacheev/cleanenv) - [cleanenv](https://github.com/ilyakaznacheev/cleanenv)
- [log](https://github.com/charmbracelet/log) - [log](https://github.com/charmbracelet/log)
- [mage](https://github.com/magefile/mage) - [mage](https://github.com/magefile/mage)
- written using [helix](https://helix-editor.com/)
- tested on [void linux](https://voidlinux.org/)
- hosted on [debian linux](https://www.debian.org/)
## why? ## why?

View file

@ -27,8 +27,5 @@ func routes(app *config.AppConfig) http.Handler {
mux.Get(handler.Handles, handler.Handler) mux.Get(handler.Handles, handler.Handler)
} }
// Setup home handler
mux.Get("/", handlers.HomeHandler)
return mux return mux
} }

View file

@ -3,7 +3,6 @@ package config
import ( import (
"math" "math"
"os" "os"
"time"
"git.burning.moe/celediel/burning.moe/internal/models" "git.burning.moe/celediel/burning.moe/internal/models"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
@ -36,10 +35,7 @@ type ConfigDatabase struct {
// Initialises the app wide AppConfig, loads values from environment, and set up the Logger // Initialises the app wide AppConfig, loads values from environment, and set up the Logger
func Initialise() AppConfig { func Initialise() AppConfig {
app := *defaults app := *defaults
app.Logger = log.NewWithOptions(os.Stderr, log.Options{ app.Logger = log.New(os.Stderr)
ReportTimestamp: true,
TimeFormat: time.TimeOnly,
})
// load values from config // load values from config
if cfg, err := loadConfig(); err == nil { if cfg, err := loadConfig(); err == nil {

View file

@ -1,16 +1,10 @@
package handlers package handlers
import ( import (
"fmt"
"html/template"
"net/http" "net/http"
"strings"
"time"
"git.burning.moe/celediel/burning.moe/internal/config" "git.burning.moe/celediel/burning.moe/internal/config"
"git.burning.moe/celediel/burning.moe/internal/models"
"git.burning.moe/celediel/burning.moe/internal/render" "git.burning.moe/celediel/burning.moe/internal/render"
"git.burning.moe/celediel/burning.moe/internal/td"
) )
// Handler holds data required for handlers. // Handler holds data required for handlers.
@ -23,17 +17,15 @@ var app *config.AppConfig
// The actual handlers // The actual handlers
var Handlers = []Handler{ var Handlers = []Handler{
// /about
{ {
Handles: "/about", Handles: "/about",
Handler: makeBasicHandler("about"), Handler: makeBasicHandler("about"),
}, },
// / comes last
{ {
Handles: "/projects", Handles: "/",
Handler: makeLinksHandler("projects"), Handler: makeBasicHandler("home"),
},
{
Handles: "/apps",
Handler: makeLinksHandler("apps"),
}, },
} }
@ -42,26 +34,6 @@ func Initialise(a *config.AppConfig) {
app = a app = a
} }
// HomeHandler handles /, generating data from Handlers
func HomeHandler(w http.ResponseWriter, r *http.Request) {
app.Logger.Info("Got request for homepage")
d := td.MakeBasicTemplateData(time.Now())
var pages []models.Link = []models.Link{}
for _, handler := range Handlers {
href := strings.TrimPrefix(handler.Handles, "/")
pages = append(pages, models.Link{
Href: template.URL(href),
Text: href,
})
}
d.LinkMap = make(map[string][]models.Link)
d.LinkMap["Pages"] = pages
app.Logger.Debug("handling home with some data", "data", &d)
render.RenderTemplateWithData(w, "home.page.tmpl", &d)
}
// makeBasicHandler returns a simple handler that renders a template from `name`.page.tmpl // makeBasicHandler returns a simple handler that renders a template from `name`.page.tmpl
func makeBasicHandler(name string) func(w http.ResponseWriter, r *http.Request) { func makeBasicHandler(name string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
@ -70,25 +42,3 @@ func makeBasicHandler(name string) func(w http.ResponseWriter, r *http.Request)
render.RenderTemplate(w, pageName) render.RenderTemplate(w, pageName)
} }
} }
// makeLinksHandler returns a handler for links.tmpl with template data from `name`
func makeLinksHandler(name string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
page := "links.tmpl"
template, err := render.GetTemplateFromCache(page)
if err != nil {
app.Logger.Error(fmt.Sprintf("couldn't get %s from cache", page), "err", err)
}
app.Logger.Infof("Got request for %s links page", name)
data, err := td.LoadTemplateData(name)
if err != nil {
app.Logger.Fatal("couldn't load template data for "+name, "err", err)
} else {
data.StringMap["GeneratedAt"] = template.GeneratedAt.Format(time.UnixDate)
}
app.Logger.Debug("handling a links page", "data", &data)
render.RenderTemplateWithData(w, page, &data)
}
}

View file

@ -1,9 +1,7 @@
package models package models
import ( import (
"bytes"
"html/template" "html/template"
"net/http"
"time" "time"
) )
@ -18,19 +16,3 @@ type TemplateCacheItem struct {
Template *template.Template Template *template.Template
GeneratedAt time.Time GeneratedAt time.Time
} }
// Execute writes the template to the supplied writer using the supplied data.
func (self *TemplateCacheItem) Execute(d *TemplateData, w http.ResponseWriter) error {
buf := new(bytes.Buffer)
err := self.Template.Execute(buf, d)
if err != nil {
return err
}
_, err = buf.WriteTo(w)
if err != nil {
return err
}
return nil
}

View file

@ -1,7 +1,7 @@
package render package render
import ( import (
"errors" "bytes"
"fmt" "fmt"
"html/template" "html/template"
"net/http" "net/http"
@ -16,20 +16,20 @@ import (
const ( const (
templatesDir string = "./templates/" templatesDir string = "./templates/"
layoutGlob string = "*.layout.tmpl" layoutGlob string = "*.layout.tmpl"
pageGlob string = "*.tmpl" pageGlob string = "*.page.tmpl"
) )
var app *config.AppConfig var app *config.AppConfig
// Initialise the render package. // Initialise the render package.
func Initialise(a *config.AppConfig) { func Initialise(a *config.AppConfig) {
var err error
app = a app = a
if app.UseCache { if app.UseCache {
var err error
app.TemplateCache, err = GenerateNewTemplateCache() app.TemplateCache, err = GenerateNewTemplateCache()
if err != nil { }
app.Logger.Fatal("Error generating template cache, bailing out!") if err != nil {
} app.Logger.Fatal("Error generating template cache, bailing out!")
} }
} }
@ -83,73 +83,30 @@ func GenerateNewTemplateCache() (models.TemplateCache, error) {
// RenderTemplate renders requested template (t), pulling from cache. // RenderTemplate renders requested template (t), pulling from cache.
func RenderTemplate(w http.ResponseWriter, filename string) { func RenderTemplate(w http.ResponseWriter, filename string) {
// TODO: implement this better
if !app.UseCache { if !app.UseCache {
RegenerateTemplateCache() c, err := GenerateNewTemplateCache()
if err != nil {
app.Logger.Fatal("Error generating template cache, bailing out!")
}
app.TemplateCache = c
} }
template, err := GetTemplateFromCache(filename) // Get templates from cache
if err != nil { template, ok := app.TemplateCache.Cache[filename]
app.Logger.Fatalf("Tried loading %s from the cache, but %s!", filename, err) if !ok {
} app.Logger.Errorf("Couldn't get %s from template cache, dunno what happened, but we're gonna generate a new one", filename)
c, err := GenerateNewTemplateCache()
data, err := GetOrGenerateTemplateData(filename) if err != nil {
if err != nil { app.Logger.Fatal("Error generating template cache, bailing out!")
app.Logger.Error(err) }
} app.TemplateCache = c
template = app.TemplateCache.Cache[filename]
app.Logger.Debug(fmt.Sprintf("Executing template %s", filename), "data", &data)
err = template.Execute(data, w)
if err != nil {
app.Logger.Fatalf("Failed to execute template %s: %s", filename, err)
}
}
func RenderTemplateWithData(w http.ResponseWriter, filename string, data *models.TemplateData) {
if !app.UseCache {
RegenerateTemplateCache()
}
template, err := GetTemplateFromCache(filename)
if err != nil {
app.Logger.Fatalf("Tried loading %s from the cache, but %s!", filename, err)
}
app.Logger.Debug(fmt.Sprintf("Executing template %s", filename), "data", &data)
err = template.Execute(data, w)
if err != nil {
app.Logger.Fatalf("Failed to execute template %s: %s", filename, err)
}
}
func RegenerateTemplateCache() {
c, err := GenerateNewTemplateCache()
if err != nil {
app.Logger.Fatal("Error generating template cache, bailing out!")
}
app.TemplateCache = c
}
// GetTemplateFromCache gets templates from cache
func GetTemplateFromCache(filename string) (*models.TemplateCacheItem, error) {
if template, ok := app.TemplateCache.Cache[filename]; ok {
return &template, nil
} else {
return &models.TemplateCacheItem{}, errors.New("Couldn't load template from cache")
}
}
// GetOrGenerateTemplateData gets template data from file, or generate simple
func GetOrGenerateTemplateData(filename string) (*models.TemplateData, error) {
template, err := GetTemplateFromCache(filename)
if err != nil {
return &models.TemplateData{}, err
} }
// Get template data from file, or generate simple
data, err := td.LoadTemplateData(filename) data, err := td.LoadTemplateData(filename)
if err == nil { if err == nil {
app.Logger.Debug(fmt.Sprintf("Loaded data for template %s.", filename), "data", &data) app.Logger.Debug(fmt.Sprintf("Loaded data for template %s.", filename), "data", data)
if _, ok := data.StringMap["GeneratedAt"]; !ok { if _, ok := data.StringMap["GeneratedAt"]; !ok {
data.StringMap["GeneratedAt"] = template.GeneratedAt.Format(time.UnixDate) data.StringMap["GeneratedAt"] = template.GeneratedAt.Format(time.UnixDate)
} }
@ -158,5 +115,15 @@ func GetOrGenerateTemplateData(filename string) (*models.TemplateData, error) {
data = td.MakeBasicTemplateData(template.GeneratedAt) data = td.MakeBasicTemplateData(template.GeneratedAt)
} }
return &data, nil // Execute templates in a new buffer
buf := new(bytes.Buffer)
err = template.Template.Execute(buf, data)
if err != nil {
app.Logger.Fatal(fmt.Sprintf("Error executing template %s! Goodbye!", filename), "err", err)
}
_, err = buf.WriteTo(w)
if err != nil {
app.Logger.Error(fmt.Sprintf("Error writing template %s!", filename), "err", err)
}
} }

View file

@ -16,8 +16,8 @@ const dataDir string = "./templates/data/"
// in order of precedence // in order of precedence
var dataExtensions = [4]string{"yml", "yaml", "toml", "json"} var dataExtensions = [4]string{"yml", "yaml", "toml", "json"}
// makeBasicTemplateData creates a blank TemplateData // makeBasicTemplateData creates a blank TemplateData containing only the
// containing only the time the template was generated // time the related template was generated
func MakeBasicTemplateData(when time.Time) models.TemplateData { func MakeBasicTemplateData(when time.Time) models.TemplateData {
strMap := map[string]string{ strMap := map[string]string{
"GeneratedAt": when.Format(time.UnixDate), "GeneratedAt": when.Format(time.UnixDate),
@ -33,16 +33,13 @@ func MakeBasicTemplateData(when time.Time) models.TemplateData {
// fails, it returns an empty TemplateData and an error // fails, it returns an empty TemplateData and an error
func LoadTemplateData(page string) (models.TemplateData, error) { func LoadTemplateData(page string) (models.TemplateData, error) {
var data models.TemplateData var data models.TemplateData
output := dataDir + strings.ReplaceAll(page, ".tmpl", "") output := dataDir + strings.ReplaceAll(page, "tmpl", "")
for _, extension := range dataExtensions { for _, extension := range dataExtensions {
if info, err := os.Stat(output + "." + extension); err == nil && !info.IsDir() { if info, err := os.Stat(output + extension); err == nil && !info.IsDir() {
err = cleanenv.ReadConfig(output+"."+extension, &data) err = cleanenv.ReadConfig(output+extension, &data)
if err == nil { if err == nil {
// don't try anymore files, but do setup an empty StringMap // don't try anymore files
if len(data.StringMap) == 0 {
data.StringMap = make(map[string]string)
}
return data, nil return data, nil
} }
} }

View file

@ -1,12 +1,4 @@
@import url('https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&display=swap');
/*
TODO: update this to be a bit more modern
maybe use SASS or something
the real TODO here is finding an image that doesn't require a white background
also TODO: proper mobile layout
*/
body { body {
background: #FFF; background: #FFF;

View file

@ -9,7 +9,16 @@
<!-- personal links --> <!-- personal links -->
<h4>links</h4> <h4>links</h4>
{{- range (index .LinkMap "Personal") }} {{ range (index .LinkMap "Personal") }}
<a href="{{ .Href }}">
<span class="iconify" data-icon="{{ .Icon }}"></span>
{{ .Text }}
</a><br />
{{ end }}
<!-- web app links -->
<h4>hosted apps</h4>
{{ range (index .LinkMap "HostedApps") }}
<a href="{{ .Href }}"> <a href="{{ .Href }}">
<span class="iconify" data-icon="{{ .Icon }}"></span> <span class="iconify" data-icon="{{ .Icon }}"></span>
{{ .Text }} {{ .Text }}
@ -17,8 +26,8 @@
{{ end }} {{ end }}
<br /> <br />
<a href="/"> <a href="/">
<span class="iconify" data-icon="material-symbols:keyboard-arrow-left"></span> <span class="iconify" data-icon="material-symbols:keyboard-arrow-left"></span>
back back
</a> </a>
</span> </span>
{{ end -}} {{ end -}}

View file

@ -14,3 +14,13 @@ LinkMap:
- href: https://github.com/celediel - href: https://github.com/celediel
text: github text: github
icon: bi: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

@ -1,11 +0,0 @@
LinkMap:
hosted apps:
- 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

@ -1,25 +0,0 @@
LinkMap:
morrowind lua mods:
- href: https://git.burning.moe/celediel/morrowind-a-sinking-feeling
text: a sinking feeling - armour causes sinking in water
icon: simple-icons:lua
- href: https://git.burning.moe/celediel/morrowind-no-more-friendly-fire
text: no more friendly fire - does what it says on the tin
icon: simple-icons:lua
- href: https://git.burning.moe/celediel/morrowind-door-randomizer
text: door randomizer - randomizes destinations of cell change doors
icon: simple-icons:lua
- href: https://git.burning.moe/celediel/morrowind-more-attentive-guards
text: more attentive guards - guards follow sneaking characters and help out when attacked unjustly
icon: simple-icons:lua
other modding:
- href: https://git.burning.moe/celediel/qud-mods
text: Assorted mods for Caves of Qud (C#)
icon: teenyicons:c-sharp-solid
misc:
- href: https://git.burning.moe/celediel/poiekolon.nvim
text: poiekolon - neovim plugin to add or toggle a char at the end of a line
icon: simple-icons:lua
- href: https://git.burning.moe/celediel/burning.moe
text: burning.moe - this website
icon: file-icons:go-old

View file

@ -11,11 +11,6 @@
</a> </a>
<br /> <br />
<span id="words"> <span id="words">
<!--
<a href="about">about</a> <a href="about">about</a>
-->
{{ range (index .LinkMap "Pages")}}
<a href="{{ .Href }}">{{ .Text }}</a><br />
{{ end }}
</span> </span>
{{ end -}} {{ end -}}

View file

@ -1,25 +0,0 @@
{{- template "base" . -}}
{{- define "content" }}
<span id="words">
{{- range $key, $value := .LinkMap }}
<h4>{{ $key }}</h4>
{{- range $value }}
<a href="{{ .Href }}">
{{- if (ne .Icon "") }}
<span class="iconify" data-icon="{{ .Icon }}"></span>
{{ end }}
{{- .Text }}
</a><br />
{{- end }}
{{ end -}}
<br />
<a href="/">
<span class="iconify" data-icon="material-symbols:keyboard-arrow-left"></span>
back
</a>
</span>
{{ end -}}
{{- define "js" }}
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
{{ end -}}