diff --git a/controller/controller.go b/controller/controller.go index 000b938..53a0c6e 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -131,11 +131,12 @@ func (t *Controller) cachePage(c echo.Context, p Page, html *bytes.Buffer) { // 1. The layout/based template specified in Page.Layout // 2. The content template specified in Page.Name // 3. All templates within the components directory +// Also included is the function map provided by the funcmap package func (t *Controller) parsePageTemplates(p Page) error { // Check if the template has not yet been parsed or if the app environment is local, so that templates reflect // changes without having the restart the server if _, ok := templates.Load(p.Name); !ok || t.Container.Config.App.Environment == config.EnvLocal { - // Parse the Layout and Name templates + // Parse the Layout and Name templates along with the function map parsed, err := template.New(p.Layout+config.TemplateExt). Funcs(funcMap). diff --git a/funcmap/funcmap.go b/funcmap/funcmap.go index f032553..e847b11 100644 --- a/funcmap/funcmap.go +++ b/funcmap/funcmap.go @@ -12,14 +12,19 @@ import ( "github.com/labstack/gommon/random" ) -// CacheKey stores a random string used as a cache key for static files -var CacheKey = random.String(10) +var ( + // CacheBuster stores a random string used as a cache buster for static files. + CacheBuster = random.String(10) +) +// GetFuncMap provides a template function map func GetFuncMap() template.FuncMap { // See http://masterminds.github.io/sprig/ for available funcs funcMap := sprig.FuncMap() // Provide a list of custom functions + // Expand this as you add more functions to this package + // Avoid using a name already in use by sprig f := template.FuncMap{ "hasField": HasField, "file": File, @@ -45,11 +50,12 @@ func HasField(v interface{}, name string) bool { return rv.FieldByName(name).IsValid() } -// File appends a cache key to a given filepath so it can remain cached until the app is restarted +// File appends a cache buster to a given filepath so it can remain cached until the app is restarted func File(filepath string) string { - return fmt.Sprintf("/%s/%s?v=%s", config.StaticPrefix, filepath, CacheKey) + return fmt.Sprintf("/%s/%s?v=%s", config.StaticPrefix, filepath, CacheBuster) } +// Link outputs HTML for a link element, providing the ability to dynamically set the active class func Link(url, text, currentPath string, classes ...string) template.HTML { if currentPath == url { classes = append(classes, "is-active") diff --git a/funcmap/funcmap_test.go b/funcmap/funcmap_test.go new file mode 100644 index 0000000..8c27005 --- /dev/null +++ b/funcmap/funcmap_test.go @@ -0,0 +1,39 @@ +package funcmap + +import ( + "fmt" + "testing" + + "goweb/config" + + "github.com/stretchr/testify/assert" +) + +func TestHasField(t *testing.T) { + type example struct { + name string + } + var e example + assert.True(t, HasField(e, "name")) + assert.False(t, HasField(e, "abcd")) +} + +func TestLink(t *testing.T) { + link := string(Link("/abc", "Text", "/abc")) + expected := `Text` + assert.Equal(t, expected, link) + + link = string(Link("/abc", "Text", "/abc", "first", "second")) + expected = `Text` + assert.Equal(t, expected, link) + + link = string(Link("/abc", "Text", "/def")) + expected = `Text` + assert.Equal(t, expected, link) +} + +func TestGetFuncMap(t *testing.T) { + file := File("test.png") + expected := fmt.Sprintf("/%s/test.png?v=%s", config.StaticPrefix, CacheBuster) + assert.Equal(t, expected, file) +}