All checks were successful
Tests / unit-tests (push) Successful in 51s
- Login sa session cookie autentifikacijom - Lista projekata iz filesystem-a - Chat sa Claude CLI preko WebSocket-a - Streaming NDJSON parsiranje iz CLI stdout-a - Sesija zivi nezavisno od browsera (reconnect replay) - Sidebar sa .md fajlovima i markdown renderovanjem - Dark tema, htmx + Go templates - 47 unit testova Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
56 lines
1.0 KiB
Go
56 lines
1.0 KiB
Go
package main
|
|
|
|
import (
|
|
"html/template"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
)
|
|
|
|
type TemplateRenderer struct {
|
|
dir string
|
|
templates map[string]*template.Template
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func NewTemplateRenderer(dir string) (*TemplateRenderer, error) {
|
|
tr := &TemplateRenderer{
|
|
dir: dir,
|
|
templates: make(map[string]*template.Template),
|
|
}
|
|
if err := tr.loadAll(); err != nil {
|
|
return nil, err
|
|
}
|
|
return tr, nil
|
|
}
|
|
|
|
func (tr *TemplateRenderer) loadAll() error {
|
|
entries, err := os.ReadDir(tr.dir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, e := range entries {
|
|
if e.IsDir() || filepath.Ext(e.Name()) != ".html" {
|
|
continue
|
|
}
|
|
path := filepath.Join(tr.dir, e.Name())
|
|
tmpl, err := template.ParseFiles(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tr.templates[e.Name()] = tmpl
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (tr *TemplateRenderer) Render(w io.Writer, name string, data any) error {
|
|
tr.mu.RLock()
|
|
tmpl, ok := tr.templates[name]
|
|
tr.mu.RUnlock()
|
|
if !ok {
|
|
return os.ErrNotExist
|
|
}
|
|
return tmpl.Execute(w, data)
|
|
}
|