Implements a Go-based CMS for editing Hugo posts and uploading images via the GitHub REST API, with no database and Git as the source of truth. Features: - Single admin auth with bcrypt password and signed session cookies - Dashboard, post listing with search, create/edit with EasyMDE editor - Media library for static/uploads/ with drag-drop and clipboard paste - Client-side autosave, unsaved changes warning, dark mode, responsive UI - Modular packages for auth, github, posts, media, session, and handlers Co-authored-by: codegirl007 <s.raide@gmail.com>
72 lines
1.3 KiB
Go
72 lines
1.3 KiB
Go
package templates
|
|
|
|
import (
|
|
"embed"
|
|
"html/template"
|
|
"io"
|
|
"io/fs"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
//go:embed all:templates
|
|
var templateFS embed.FS
|
|
|
|
//go:embed all:static
|
|
var staticFS embed.FS
|
|
|
|
// Renderer renders HTML templates with shared layout and functions.
|
|
type Renderer struct {
|
|
templates *template.Template
|
|
}
|
|
|
|
// New creates a template renderer.
|
|
func New() (*Renderer, error) {
|
|
funcs := template.FuncMap{
|
|
"formatDate": formatDate,
|
|
"draftBadge": draftBadgeClass,
|
|
}
|
|
|
|
tmpl, err := template.New("").Funcs(funcs).ParseFS(templateFS, "templates/*.html")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Renderer{templates: tmpl}, nil
|
|
}
|
|
|
|
// Render executes a named template with data.
|
|
func (r *Renderer) Render(w io.Writer, name string, data any) error {
|
|
return r.templates.ExecuteTemplate(w, name, data)
|
|
}
|
|
|
|
// StaticHandler serves embedded static assets.
|
|
func StaticHandler() http.Handler {
|
|
sub, err := fs.Sub(staticFS, "static")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return http.FileServer(http.FS(sub))
|
|
}
|
|
|
|
func formatDate(t any) string {
|
|
switch v := t.(type) {
|
|
case time.Time:
|
|
if v.IsZero() {
|
|
return "—"
|
|
}
|
|
return v.Format("Jan 2, 2006")
|
|
case string:
|
|
return v
|
|
default:
|
|
return "—"
|
|
}
|
|
}
|
|
|
|
func draftBadgeClass(draft bool) string {
|
|
if draft {
|
|
return "badge-draft"
|
|
}
|
|
return "badge-published"
|
|
}
|