it works!
initial build that basically replicates my old HTML site
This commit is contained in:
parent
0d809bfea8
commit
a7f6bb35e7
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
bin/
|
31
cmd/web/main.go
Normal file
31
cmd/web/main.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Main entry point for the web app. Does all
|
||||||
|
// the setup, then runs the http server.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/config"
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/handlers"
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/render"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialise app and config
|
||||||
|
app := config.Initialise()
|
||||||
|
|
||||||
|
// Initialise handlers and renderer
|
||||||
|
handlers.Initialise(&app)
|
||||||
|
render.Initialise(&app)
|
||||||
|
|
||||||
|
// Initialise the webserver
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: fmt.Sprintf(":%d", app.ListenPort),
|
||||||
|
Handler: routes(&app),
|
||||||
|
}
|
||||||
|
|
||||||
|
// and finally, start the server
|
||||||
|
app.Logger.Printf("Listening on port %d", app.ListenPort)
|
||||||
|
srv.ListenAndServe()
|
||||||
|
}
|
31
cmd/web/routes.go
Normal file
31
cmd/web/routes.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/config"
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/handlers"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
// routes handles all of the HTTP setup. Middleware is enabled,
|
||||||
|
// static fileserver is setup, and handlers are ... handled
|
||||||
|
func routes(app *config.AppConfig) http.Handler {
|
||||||
|
mux := chi.NewRouter()
|
||||||
|
|
||||||
|
// Import some middleware
|
||||||
|
mux.Use(middleware.Recoverer)
|
||||||
|
|
||||||
|
// Setup static file server
|
||||||
|
app.Logger.Debug("Setting up /static file server")
|
||||||
|
mux.Handle("/static/*", http.StripPrefix("/static", http.FileServer(http.Dir("./static"))))
|
||||||
|
|
||||||
|
// Setup routes for handlers
|
||||||
|
for _, handler := range handlers.Handlers {
|
||||||
|
app.Logger.Info("Setting up handler for " + handler.Handles)
|
||||||
|
mux.Get(handler.Handles, handler.Handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mux
|
||||||
|
}
|
25
go.mod
25
go.mod
|
@ -1,3 +1,28 @@
|
||||||
module git.burning.moe/celediel/burning.moe
|
module git.burning.moe/celediel/burning.moe
|
||||||
|
|
||||||
go 1.21.5
|
go 1.21.5
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-chi/chi/v5 v5.0.11
|
||||||
|
github.com/ilyakaznacheev/cleanenv v1.5.0
|
||||||
|
github.com/magefile/mage v1.15.0
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/muesli/reflow v0.3.0 // indirect
|
||||||
|
github.com/muesli/termenv v0.15.2 // indirect
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
43
go.sum
Normal file
43
go.sum
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
|
||||||
|
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/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=
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
|
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
|
||||||
|
github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
|
||||||
|
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||||
|
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||||
|
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
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/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=
|
||||||
|
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/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=
|
||||||
|
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ=
|
||||||
|
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw=
|
83
internal/config/config.go
Normal file
83
internal/config/config.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/models"
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
"github.com/ilyakaznacheev/cleanenv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AppConfig contains data to be accessed across the app.
|
||||||
|
type AppConfig struct {
|
||||||
|
ListenPort uint16
|
||||||
|
TemplateCache models.TemplateCache
|
||||||
|
UseCache bool
|
||||||
|
Logger *log.Logger
|
||||||
|
LogLevel log.Level
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaluts contains default settings that are used if no environmental variables are set
|
||||||
|
var defaults = &AppConfig{
|
||||||
|
ListenPort: 9001,
|
||||||
|
UseCache: true,
|
||||||
|
LogLevel: log.InfoLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigDatabase contains data to be loaded from environmental variables
|
||||||
|
type ConfigDatabase struct {
|
||||||
|
Port uint16 `env:"PORT" env-default:"9001" env-description:"server port"`
|
||||||
|
LogLevel string `env:"LOGLEVEL" env-default:"warn" env-description:"Logging level. Default: warn, Possible values: debug info warn error fatal none"`
|
||||||
|
UseCache bool `env:"CACHE" env-default:"true" env-description:"Use template cache"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialises the app wide AppConfig, loads values from environment, and set up the Logger
|
||||||
|
func Initialise() AppConfig {
|
||||||
|
app := *defaults
|
||||||
|
app.Logger = log.New(os.Stderr)
|
||||||
|
|
||||||
|
// load values from config
|
||||||
|
if cfg, err := loadConfig(); err == nil {
|
||||||
|
app.ListenPort = cfg.Port
|
||||||
|
app.UseCache = cfg.UseCache
|
||||||
|
app.LogLevel = logLevelFromString(cfg.LogLevel)
|
||||||
|
} else {
|
||||||
|
app.Logger.Print("Failed loading config from environment", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Logger.SetLevel(app.LogLevel)
|
||||||
|
app.Logger.Debug("Loaded config from environment:", "port", app.ListenPort, "useCache", app.UseCache, "log_level", app.LogLevel)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadConfig utilises cleanenv to load config values from the environment
|
||||||
|
func loadConfig() (ConfigDatabase, error) {
|
||||||
|
var cfg ConfigDatabase
|
||||||
|
if err := cleanenv.ReadEnv(&cfg); err != nil {
|
||||||
|
return ConfigDatabase{}, err
|
||||||
|
} else {
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// logLevelFromString turns a string like "warn" into a log.Level like log.WarnLevel
|
||||||
|
func logLevelFromString(level string) log.Level {
|
||||||
|
switch level {
|
||||||
|
case "debug":
|
||||||
|
return log.DebugLevel
|
||||||
|
case "info":
|
||||||
|
return log.InfoLevel
|
||||||
|
case "warn":
|
||||||
|
return log.WarnLevel
|
||||||
|
case "error":
|
||||||
|
return log.ErrorLevel
|
||||||
|
case "fatal":
|
||||||
|
return log.FatalLevel
|
||||||
|
case "none":
|
||||||
|
return math.MaxInt32
|
||||||
|
default:
|
||||||
|
return defaults.LogLevel
|
||||||
|
}
|
||||||
|
}
|
42
internal/handlers/handlers.go
Normal file
42
internal/handlers/handlers.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/config"
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/models"
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/render"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler holds data required for handlers.
|
||||||
|
type Handler struct {
|
||||||
|
Handles string
|
||||||
|
Handler func(w http.ResponseWriter, r *http.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
var app *config.AppConfig
|
||||||
|
|
||||||
|
// The actual handlers
|
||||||
|
var Handlers = []Handler{
|
||||||
|
// /about
|
||||||
|
{
|
||||||
|
Handles: "/about",
|
||||||
|
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
app.Logger.Info("Got request for about page.")
|
||||||
|
render.RenderTemplate(w, "about.page", &models.TemplateData{})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// / comes last
|
||||||
|
{
|
||||||
|
Handles: "/",
|
||||||
|
Handler: func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
app.Logger.Info("Got request for homepage.")
|
||||||
|
render.RenderTemplate(w, "home.page", &models.TemplateData{})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise the handlers package.
|
||||||
|
func Initialise(a *config.AppConfig) {
|
||||||
|
app = a
|
||||||
|
}
|
18
internal/models/templatecache.go
Normal file
18
internal/models/templatecache.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TemplateCache holds the template cache as map of TemplateCacheItem
|
||||||
|
type TemplateCache struct {
|
||||||
|
Cache map[string]TemplateCacheItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateCacheItem holds a pointer to a generated
|
||||||
|
// template, and the time it was generated at.
|
||||||
|
type TemplateCacheItem struct {
|
||||||
|
Template *template.Template
|
||||||
|
GeneratedAt time.Time
|
||||||
|
}
|
14
internal/models/templatedata.go
Normal file
14
internal/models/templatedata.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
// TemplateData holds data sent from handlers to templates.
|
||||||
|
type TemplateData struct {
|
||||||
|
StringMap map[string]string
|
||||||
|
IntMap map[string]int
|
||||||
|
FloatMap map[string]float32
|
||||||
|
Data map[string]interface{}
|
||||||
|
CSRFToken string
|
||||||
|
Flash string
|
||||||
|
Warning string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
111
internal/render/render.go
Normal file
111
internal/render/render.go
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/config"
|
||||||
|
"git.burning.moe/celediel/burning.moe/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
templatesDir string = "./templates/"
|
||||||
|
layoutGlob string = "*.layout.tmpl"
|
||||||
|
pageGlob string = "*.page.tmpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
var app *config.AppConfig
|
||||||
|
|
||||||
|
// Initialise the render package.
|
||||||
|
func Initialise(a *config.AppConfig) {
|
||||||
|
var err error
|
||||||
|
app = a
|
||||||
|
app.TemplateCache, err = GenerateNewTemplateCache()
|
||||||
|
if err != nil {
|
||||||
|
app.Logger.Fatal("Error generating template cache, bailing out!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateNewTemplateCache generates a new template cache.
|
||||||
|
func GenerateNewTemplateCache() (models.TemplateCache, error) {
|
||||||
|
// start with an empty map
|
||||||
|
cache := models.TemplateCache{}
|
||||||
|
cache.Cache = map[string]models.TemplateCacheItem{}
|
||||||
|
|
||||||
|
// Generate a list of pages based on globs
|
||||||
|
pages, err := filepath.Glob(templatesDir + pageGlob)
|
||||||
|
|
||||||
|
// a nice try catch would be pretty cool right about here
|
||||||
|
if err != nil {
|
||||||
|
return cache, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate each page, parsing the file and adding it to the cache
|
||||||
|
for _, page := range pages {
|
||||||
|
name := filepath.Base(page)
|
||||||
|
app.Logger.Info("Generating template " + name)
|
||||||
|
|
||||||
|
templateSet, err := template.New(name).ParseFiles(page)
|
||||||
|
if err != nil {
|
||||||
|
return cache, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glob and parse any layouts found
|
||||||
|
layouts, err := filepath.Glob(templatesDir + layoutGlob)
|
||||||
|
if err != nil {
|
||||||
|
return cache, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(layouts) > 0 {
|
||||||
|
templateSet, err = templateSet.ParseGlob(templatesDir + layoutGlob)
|
||||||
|
if err != nil {
|
||||||
|
return cache, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache.Cache[name] = models.TemplateCacheItem{
|
||||||
|
Template: templateSet,
|
||||||
|
GeneratedAt: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All was good, so return the cache, and no error
|
||||||
|
return cache, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderTemplate renders requested template (t), pulling from cache.
|
||||||
|
func RenderTemplate(w http.ResponseWriter, t string, data *models.TemplateData) {
|
||||||
|
filename := t + ".tmpl"
|
||||||
|
var cache models.TemplateCache
|
||||||
|
if app.UseCache {
|
||||||
|
cache = app.TemplateCache
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
cache, err = GenerateNewTemplateCache()
|
||||||
|
if err != nil {
|
||||||
|
app.Logger.Fatal("Error generating template cache, bailing out!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get templates from cache
|
||||||
|
template, ok := cache.Cache[filename]
|
||||||
|
if !ok {
|
||||||
|
app.Logger.Fatal(fmt.Sprintf("Couldn't get %s from template cache, bailing out!", filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute templates in a new buffer
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err := template.Template.Execute(buf, data)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
app.Logger.Fatal("Error executing template %s! Goodbye!", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = buf.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
app.Logger.Error("Error writing template %s!\n", "err", err)
|
||||||
|
}
|
||||||
|
}
|
38
magefile.go
Normal file
38
magefile.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//go:build mage
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/magefile/mage/sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
binaryName string = "burningmoe"
|
||||||
|
buildDir string = "bin"
|
||||||
|
cmd string = fmt.Sprintf(".%[1]ccmd%[1]cweb", os.PathSeparator)
|
||||||
|
output string = fmt.Sprintf(".%[1]c%[2]s%[1]c%[3]s", os.PathSeparator, buildDir, binaryName)
|
||||||
|
)
|
||||||
|
|
||||||
|
func Build() error {
|
||||||
|
fmt.Println("Building...")
|
||||||
|
return sh.Run("go", "build", "-o", output, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run() error {
|
||||||
|
fmt.Println("Running...")
|
||||||
|
return sh.Run("go", "run", cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunBinary() error {
|
||||||
|
Build()
|
||||||
|
fmt.Println("Running binary...")
|
||||||
|
return sh.Run(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clean() error {
|
||||||
|
fmt.Println("Cleaning...")
|
||||||
|
return os.Remove(output)
|
||||||
|
}
|
71
static/css/style.css
Normal file
71
static/css/style.css
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #FFF;
|
||||||
|
color: #121212;
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Gloria Hallelujah', cursive;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
-o-transition: .5s;
|
||||||
|
-ms-transition: .5s;
|
||||||
|
-moz-transition: .5s;
|
||||||
|
-webkit-transition: .5s;
|
||||||
|
/* ...and now for the proper property */
|
||||||
|
transition: .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.back {
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stuff {
|
||||||
|
margin: 55px 150px 25px 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#words {
|
||||||
|
font-size: 1.0em;
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bigwords {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#leftfooter {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
font-size: 0.75em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rightfooter {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
font-size: 0.75em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
margin: 0px;
|
||||||
|
margin-top: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.7em;
|
||||||
|
font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", Meiryo, "MS Pゴシック", "MS PGothic", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
padding-top: 0px;
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
BIN
static/img/burningmoe.jpg
Normal file
BIN
static/img/burningmoe.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 243 KiB |
BIN
static/img/moemoe.png
Normal file
BIN
static/img/moemoe.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
53
templates/about.page.tmpl
Normal file
53
templates/about.page.tmpl
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{{- template "base" . -}}
|
||||||
|
|
||||||
|
{{- define "content" }}
|
||||||
|
<span id="words">
|
||||||
|
<h4>celediel</h4>
|
||||||
|
<span id="bigwords">
|
||||||
|
she/her, 1989, queer anarchist, self-taught aspiring developer
|
||||||
|
</span>
|
||||||
|
<h4>links</h4>
|
||||||
|
|
||||||
|
<!-- personal links -->
|
||||||
|
<a href="https://matrix.to/#/@celediel:burning.moe">
|
||||||
|
<span class="iconify" data-icon="tabler:brand-matrix"></span>
|
||||||
|
matrix
|
||||||
|
</a><br />
|
||||||
|
|
||||||
|
<a href="https://slrpnk.net/u/Celediel">
|
||||||
|
<span class="iconify" data-icon="simple-icons:lemmy"></span>
|
||||||
|
lemmy
|
||||||
|
</a><br />
|
||||||
|
|
||||||
|
<a href="https://git.burning.moe/celediel">
|
||||||
|
<span class="iconify" data-icon="mdi:git"></span>
|
||||||
|
self-hosted git
|
||||||
|
</a><br />
|
||||||
|
|
||||||
|
<a href="https://github.com/celediel">
|
||||||
|
<span class="iconify" data-icon="bi:github"></span>
|
||||||
|
github
|
||||||
|
</a><br />
|
||||||
|
|
||||||
|
<!-- web app links -->
|
||||||
|
<h4>hosted apps</h4>
|
||||||
|
<a href="https://git.burning.moe/">
|
||||||
|
<span class="iconify" data-icon="mdi:git"></span>
|
||||||
|
self-hosted git
|
||||||
|
</a><br />
|
||||||
|
<a href="https://bin.burning.moe/">
|
||||||
|
<span class="iconify" data-icon="fluent:bin-recycle-20-filled"></span>
|
||||||
|
wastebin
|
||||||
|
</a><br />
|
||||||
|
<a href="https://gist.burning.moe/">
|
||||||
|
<span class="iconify" data-icon="carbon:paste"></span>
|
||||||
|
gist
|
||||||
|
</a>
|
||||||
|
<br /><br />
|
||||||
|
<a href="/">back</a>
|
||||||
|
</span>
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
{{- define "js" }}
|
||||||
|
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
|
||||||
|
{{ end -}}
|
37
templates/base.layout.tmpl
Normal file
37
templates/base.layout.tmpl
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{{- define "base" -}}
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>burning.moe</title>
|
||||||
|
<link rel="stylesheet" href="static/css/style.css">
|
||||||
|
{{- block "css" . }}
|
||||||
|
{{- end }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="stuff">
|
||||||
|
{{- block "content" . }}
|
||||||
|
{{ end -}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{- block "js" . }}
|
||||||
|
{{ end -}}
|
||||||
|
<div id="leftfooter">
|
||||||
|
note: please do not set fire to cute girls
|
||||||
|
</div>
|
||||||
|
<div id="rightfooter">
|
||||||
|
powered by
|
||||||
|
<a href="https://www.debian.org/">debian</a>
|
||||||
|
and
|
||||||
|
<a href="https://go.dev/">go</a>,
|
||||||
|
proxied by
|
||||||
|
<a href="https://caddyserver.com/">caddy</a>
|
||||||
|
-
|
||||||
|
<a href="https://git.burning.moe/celediel/burning.moe">source</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end -}}
|
16
templates/home.page.tmpl
Normal file
16
templates/home.page.tmpl
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{{- template "base" . -}}
|
||||||
|
|
||||||
|
{{- define "content" }}
|
||||||
|
<img src="static/img/moemoe.png">
|
||||||
|
<div id="header">
|
||||||
|
<!-- <h1>燃え 萌え</h1> -->
|
||||||
|
<h2>burning.moe</h2>
|
||||||
|
</div>
|
||||||
|
<a href="http://www.pixiv.net/member_illust.php?mode=medium&illust_id=22647957">
|
||||||
|
<img src="static/img/burningmoe.jpg" style="max-width:400px;" />
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<span id="words">
|
||||||
|
<a href="about">about</a>
|
||||||
|
</span>
|
||||||
|
{{ end -}}
|
Loading…
Reference in a new issue