github.com/gocaveman/caveman@v0.0.0-20191211162744-0ddf99dbdf6e/themes/themetester/main.go (about)

     1  // The themetester is a standalone executable intended to help internal dev and testing of Caveman themes.
     2  // It is also intended to be easy to copy or modify for your own theme development.
     3  package main
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"log"
     9  	"net/http"
    10  	"sort"
    11  	"sync"
    12  
    13  	"github.com/gocaveman/caveman/autowire"
    14  	"github.com/gocaveman/caveman/renderer"
    15  	"github.com/gocaveman/caveman/tmpl"
    16  	"github.com/gocaveman/caveman/webutil"
    17  	"github.com/gocaveman/caveman/webutil/handlerregistry"
    18  	"github.com/spf13/pflag"
    19  	"github.com/spf13/viper"
    20  
    21  	"github.com/gocaveman/caveman/themes/paleolithic"
    22  	"github.com/gocaveman/caveman/themes/pleistocene"
    23  )
    24  
    25  func main() {
    26  
    27  	themes := make(map[string]tmpl.Store)
    28  
    29  	// add each theme you want to be available here
    30  	defaultTheme := "paleolithic"
    31  	themes["paleolithic"] = paleolithic.NewTmplStore()
    32  	themes["pleistocene"] = pleistocene.NewTmplStore()
    33  
    34  	pflag.StringP("http-listen", "l", ":2666", "IP:Port to listen on for HTTP")
    35  	pflag.StringP("default-theme", "", defaultTheme, "Default theme name on startup")
    36  	pflag.Parse()
    37  	viper.BindPFlags(pflag.CommandLine)
    38  
    39  	defaultTheme = viper.GetString("default-theme")
    40  	syncStore := tmpl.NewSyncStore(themes[defaultTheme])
    41  
    42  	themeSwitchHandler := &ThemeSwitchHandler{
    43  		SyncStore:    syncStore,
    44  		DefaultTheme: defaultTheme,
    45  		ThemeMap:     themes,
    46  	}
    47  
    48  	hl := webutil.NewDefaultHandlerList()
    49  	hl = append(hl, themeSwitchHandler)
    50  	for _, item := range handlerregistry.Contents() {
    51  		hl = append(hl, item.Value)
    52  	}
    53  
    54  	rend := renderer.NewFromTemplateReader(syncStore)
    55  	autowire.Provide("", rend)
    56  	rendHandler := renderer.NewHandler(rend)
    57  	hl = append(hl, rendHandler)
    58  	hl = append(hl, renderer.NotFoundHandler(rend, "/_404.gohtml"))
    59  
    60  	err := autowire.Contents().Run()
    61  	if err != nil {
    62  		log.Fatalf("autowire error: %v", err)
    63  	}
    64  
    65  	var wg sync.WaitGroup
    66  
    67  	httpListen := viper.GetString("http-listen")
    68  	webutil.StartHTTPServer(&http.Server{
    69  		Addr:    httpListen,
    70  		Handler: hl,
    71  	}, &wg)
    72  
    73  	log.Printf("Web server starting at %q; use %q to set the theme", httpListen, `/api/theme-switch?id=`+defaultTheme)
    74  
    75  	wg.Wait()
    76  }
    77  
    78  type ThemeSwitchHandler struct {
    79  	SyncStore    *tmpl.SyncStore
    80  	DefaultTheme string
    81  	CurrentTheme string
    82  	ThemeMap     map[string]tmpl.Store
    83  	sync.RWMutex
    84  }
    85  
    86  func (h *ThemeSwitchHandler) ServeHTTPChain(w http.ResponseWriter, r *http.Request) (w2 http.ResponseWriter, r2 *http.Request) {
    87  
    88  	w2, r2 = w, r
    89  
    90  	if r.URL.Path == "/api/theme-switch" {
    91  
    92  		h.Lock()
    93  		defer h.Unlock()
    94  
    95  		w.Header().Set("content-type", "application/json")
    96  		id := r.FormValue("id")
    97  		if _, ok := h.ThemeMap[id]; ok && id != "" {
    98  			h.CurrentTheme = id
    99  			h.SyncStore.SetStore(h.ThemeMap[h.CurrentTheme])
   100  		} else {
   101  			w.WriteHeader(400)
   102  			fmt.Fprint(w, `{"error":{"code":400,"message":"invalid id"}}`)
   103  			return
   104  		}
   105  		fmt.Fprint(w, `{"result":true}`)
   106  		return
   107  	}
   108  
   109  	h.RLock()
   110  	defer h.RUnlock()
   111  
   112  	currentTheme := h.DefaultTheme
   113  
   114  	// provide the theme info in the context
   115  	var themeNameList []string
   116  	for name := range h.ThemeMap {
   117  		themeNameList = append(themeNameList, name)
   118  	}
   119  	sort.Strings(themeNameList)
   120  
   121  	ctx := r2.Context()
   122  	ctx = context.WithValue(ctx, "themetester.CurrentTheme", currentTheme)
   123  	ctx = context.WithValue(ctx, "themetester.DefaultTheme", h.DefaultTheme)
   124  	ctx = context.WithValue(ctx, "themetester.ThemeNameList", themeNameList)
   125  	r2 = r2.WithContext(ctx)
   126  
   127  	return
   128  }