- THE CONTENT
+ {{ block "content" . }}{{end}}
{{/*
- {{ block "content" . }}
{{ if layout == 'two_columns' }}
{{ self.title() }} {{ self.subtitle() }}
diff --git a/views/funcmap.go b/views/funcmap.go
index dff1d00b..0bc18861 100644
--- a/views/funcmap.go
+++ b/views/funcmap.go
@@ -3,69 +3,102 @@ package views
import (
"html/template"
"math/rand"
+ "net/http"
- "go.uber.org/zap"
+ "github.com/moul/sprig"
"ultre.me/calcbiz/pkg/random"
)
-func getFuncmap(opts *Options) template.FuncMap {
- f := funcmap{opts: opts}
- return template.FuncMap{
- "yomyman_style": f.yomymanStyle,
- "devel": f.devel,
- "sharing_image_url": f.sharingImageURL,
- "sharing_description": f.sharingDescription,
- "current_url": f.currentURL,
- "active_page": f.activePage,
- "resize": f.resize,
- "page_title": f.pageTitle,
- "invalid_cache": f.invalidCache,
- "logo_alternate": random.AlternateLogo,
- "mot_du_jour": random.WOTD,
- "megahertz": f.megahertz,
- "mot_debile_qui_se_mange": random.MotDebileQuiSeMange,
- "neige": func() bool { return false },
- }
+func getFuncmap(opts *Options) *ctxFuncmap {
+ f := &ctxFuncmap{opts: opts}
+
+ fm := sprig.FuncMap()
+ fm["yomyman_style"] = f.yomymanStyle
+ fm["devel"] = f.devel
+ fm["sharing_image_url"] = f.sharingImageURL
+ fm["sharing_description"] = f.sharingDescription
+ fm["current_url"] = f.currentURL
+ fm["active_page"] = f.activePage
+ fm["active_menu"] = f.activeMenu
+ fm["resize"] = f.resize
+ fm["page_title"] = f.pageTitle
+ fm["invalid_cache"] = f.invalidCache
+ fm["logo_alternate"] = random.AlternateLogo
+ fm["mot_du_jour"] = random.WOTD
+ fm["megahertz"] = f.megahertz
+ fm["mot_debile_qui_se_mange"] = random.MotDebileQuiSeMange
+ fm["neige"] = func() bool { return false }
+ fm["cache_external_assets"] = f.cacheExternalAsset
+ f.fm = fm
+ return f
}
-type funcmap struct{ opts *Options }
+type ctxFuncmap struct {
+ fm template.FuncMap
+ opts *Options
+ req *http.Request
+}
-func (f *funcmap) devel() bool { return f.opts.Debug }
+func (f *ctxFuncmap) devel() bool { return f.opts.Debug }
-func (f *funcmap) sharingImageURL() string {
+func (f *ctxFuncmap) sharingImageURL() string {
return "http://www.camembertaulaitcrew.biz/static/img/logo-300.png" // FIXME: make it dynamic
}
-func (f *funcmap) activePage() string { return "home" } // FIXME: make it dynamic
+func (f *ctxFuncmap) activePage() string {
+ return f.req.URL.Path
+}
+
+func (f *ctxFuncmap) activeMenu() string {
+ switch f.req.URL.Path {
+ case "/":
+ return "home"
+ case "/muzik":
+ // FIXME: support albums, songs
+ return "muzik"
+ case "/copaings":
+ return "copaings"
+ case "/hackz":
+ // FIXME: support hackz URLs
+ return "hackz"
+ default:
+ return "home"
+ }
+}
-func (f *funcmap) pageTitle() string { return "Camembert au lait crew" } // FIXME: make it dynamic
+func (f *ctxFuncmap) pageTitle() string { return "Camembert au lait crew" } // FIXME: make it dynamic
-func (f *funcmap) sharingDescription() string { return "c'est cool" }
+func (f *ctxFuncmap) sharingDescription() string { return "c'est cool" }
-func (f *funcmap) currentURL() string {
+func (f *ctxFuncmap) currentURL() string {
return "https://www.camembertaulaitcrew.biz/"
// FIXME: make it flexible (should be canonical url
}
-func (f *funcmap) resize(opts ...string) string {
+func (f *ctxFuncmap) cacheExternalAsset(path string) string {
+ // FIXME: implement
+ return path
+}
+
+func (f *ctxFuncmap) resize(opts ...string) string {
path := opts[len(opts)-1]
opts = opts[:len(opts)-1]
- zap.L().Debug("redize", zap.String("path", path), zap.Strings("opts", opts))
+ //zap.L().Debug("resize", zap.String("path", path), zap.Strings("opts", opts))
// FIXME: apply transform + cache + give new URL
return path
}
-func (f *funcmap) yomymanStyle() string {
+func (f *ctxFuncmap) yomymanStyle() string {
styles := []string{"cachou", "jambon", "epinard", "lasagne", "haricot", "sandwich"}
return "cool-style-" + styles[rand.Intn(len(styles))]
}
-func (f *funcmap) invalidCache() string {
+func (f *ctxFuncmap) invalidCache() string {
// FIXME: use random string (once per server start)
// FIXME: or create a new func that returns file content hash
return "no_cache_please"
}
-func (f *funcmap) megahertz() float64 {
+func (f *ctxFuncmap) megahertz() float64 {
return rand.Float64() * 100
}
diff --git a/views/util.go b/views/util.go
index 188f12ba..39bab544 100644
--- a/views/util.go
+++ b/views/util.go
@@ -18,7 +18,7 @@ var (
bufpool *bpool.BufferPool
)
-func loadTemplates(opts *Options) error {
+func (h *handlers) loadTemplates() error {
box = packr.NewBox("../templates")
bufpool = bpool.NewBufferPool(64)
templates = make(map[string]*template.Template)
@@ -40,8 +40,8 @@ func loadTemplates(opts *Options) error {
}
// generate optimized templates
- funcmap := getFuncmap(opts)
- mainTemplate := template.New("main").Funcs(funcmap)
+ h.funcmap = getFuncmap(h.opts)
+ mainTemplate := template.New("main").Funcs(h.funcmap.fm)
mainTemplate = template.Must(mainTemplate.Parse(`{{define "main"}}{{template "base" .}}{{end}}`))
mainTemplate = template.Must(mainTemplate.Parse(layoutContent))
for filepath, content := range pageContents {
@@ -52,35 +52,49 @@ func loadTemplates(opts *Options) error {
return nil
}
-func setDefaultHeaders(w http.ResponseWriter) {
- push(w, "/css/calc.css")
+func (h *handlers) setDefaultHeaders(w http.ResponseWriter) {
+ h.push(w, "/css/calc.css")
w.Header().Set("Content-Type", "text/html; charset=utf-8")
}
-func renderError(w http.ResponseWriter, r *http.Request, err error) {
+func (h *handlers) renderError(w http.ResponseWriter, r *http.Request, err error) {
zap.L().Warn("rendering error", zap.Error(err))
http.Error(w, fmt.Sprintf("Error: %v\n", err), http.StatusInternalServerError)
}
-func render(w http.ResponseWriter, r *http.Request, name string, data interface{}) {
+func (h *handlers) render(w http.ResponseWriter, r *http.Request, name string, data renderData) {
tmpl, ok := templates[name]
if !ok {
- renderError(w, r, fmt.Errorf("the template %s does not exist.", name))
+ h.renderError(w, r, fmt.Errorf("the template %s does not exist.", name))
return
}
buf := bufpool.Get()
defer bufpool.Put(buf)
+ if data == nil {
+ data = make(renderData)
+ }
+
+ data["req"] = map[string]interface{}{
+ "name": name,
+ "r": r,
+ }
+
+ // set current request in ctxFuncmap objects
+ h.mutex.Lock()
+ defer h.mutex.Unlock()
+ h.funcmap.req = r
+
if err := tmpl.Execute(buf, data); err != nil {
- renderError(w, r, err)
+ h.renderError(w, r, err)
return
}
buf.WriteTo(w)
}
-func push(w http.ResponseWriter, resource string) {
+func (h *handlers) push(w http.ResponseWriter, resource string) {
pusher, ok := w.(http.Pusher)
if ok {
if err := pusher.Push(resource, nil); err == nil {
diff --git a/views/views.go b/views/views.go
index ba5eca5c..e416524f 100644
--- a/views/views.go
+++ b/views/views.go
@@ -2,8 +2,10 @@ package views
import (
"net/http"
+ "sync"
"github.com/gorilla/mux"
+ "ultre.me/calcbiz/pkg/crew"
)
type Options struct {
@@ -12,36 +14,85 @@ type Options struct {
}
func Setup(opts *Options) error {
- if err := loadTemplates(opts); err != nil {
+ handlers := handlers{opts: opts}
+ if err := handlers.loadTemplates(); err != nil {
return err
}
- opts.Router.HandleFunc("/", homeHandler)
- opts.Router.HandleFunc("/muzik", muzikHandler)
- opts.Router.HandleFunc("/hackz", hackzHandler)
- opts.Router.HandleFunc("/copaings", copaingsHandler)
+ opts.Router.HandleFunc("/", handlers.homeHandler)
+ opts.Router.HandleFunc("/muzik", handlers.muzikHandler)
+ opts.Router.HandleFunc("/hackz", handlers.hackzHandler)
+ opts.Router.HandleFunc("/copaings", handlers.copaingsHandler)
+
+ //
+ // old routes (to be imported)
+ //
+
+ // /m1ch3l GET/POST
+ // /hackz/convertisseur
+ // /hackz/miroir
+ // /hackz/demineur
+ // /hackz/calculatrice.exe
+ // /hackz/terminul
+ // /hackz/steak-hache-shake
+ // /hackz/3615cryptage
+ // /hackz/paint
+ // /hackz/2048
+ // /hackz/ultreme-tetris
+ // /hackz/recettator
+ // /hackz/moijaime
+ // /hackz/phazms GET/POST
+ // /album/
+ // /track/
+ // /scorz/inc///
+ // /sitemap.xml
+
+ //
+ // old inactive routes
+ //
+
+ // /admin/flush-cache
+ // /vidz
+ // /tofz
+ // /test/fb
+ // /test/tototo
+ // /scorz
+
+ //
+ // new routes
+ //
+
+ // /crew
return nil
}
-func homeHandler(w http.ResponseWriter, r *http.Request) {
- setDefaultHeaders(w)
- data := map[string]interface{}{"hello": "world"}
- render(w, r, "home.tmpl", data)
+type handlers struct {
+ opts *Options
+ funcmap *ctxFuncmap
+ mutex sync.Mutex
+}
+
+type renderData map[string]interface{}
+
+func (h *handlers) homeHandler(w http.ResponseWriter, r *http.Request) {
+ h.setDefaultHeaders(w)
+ data := renderData{"hello": "world"}
+ h.render(w, r, "home.tmpl", data)
}
-func muzikHandler(w http.ResponseWriter, r *http.Request) {
- setDefaultHeaders(w)
- data := map[string]interface{}{"hello": "world"}
- render(w, r, "muzik.tmpl", data)
+func (h *handlers) muzikHandler(w http.ResponseWriter, r *http.Request) {
+ h.setDefaultHeaders(w)
+ data := renderData{"hello": "world"}
+ h.render(w, r, "muzik.tmpl", data)
}
-func copaingsHandler(w http.ResponseWriter, r *http.Request) {
- setDefaultHeaders(w)
- data := map[string]interface{}{"hello": "world"}
- render(w, r, "copaings.tmpl", data)
+func (h *handlers) copaingsHandler(w http.ResponseWriter, r *http.Request) {
+ h.setDefaultHeaders(w)
+ data := renderData{"friends": crew.CALC.Friends}
+ h.render(w, r, "copaings.tmpl", data)
}
-func hackzHandler(w http.ResponseWriter, r *http.Request) {
- setDefaultHeaders(w)
- data := map[string]interface{}{"hello": "world"}
- render(w, r, "hackz.tmpl", data)
+func (h *handlers) hackzHandler(w http.ResponseWriter, r *http.Request) {
+ h.setDefaultHeaders(w)
+ data := renderData{"hello": "world"}
+ h.render(w, r, "hackz.tmpl", data)
}