From 1490bb5ecb188db1bd8de4bbae8e0d89e84aeefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Sun, 27 Dec 2020 18:09:45 +0100 Subject: [PATCH] Add the {{date}} template helper --- adapter/handlebars/handlebars.go | 12 +++--- adapter/handlebars/handlebars_test.go | 34 +++++++++++++++-- adapter/handlebars/helpers/date.go | 54 +++++++++++++++++++++++++++ adapter/handlebars/helpers/slug.go | 1 - go.mod | 1 + go.sum | 6 +++ util/date/date.go | 32 ++++++++++++++++ 7 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 adapter/handlebars/helpers/date.go create mode 100644 util/date/date.go diff --git a/adapter/handlebars/handlebars.go b/adapter/handlebars/handlebars.go index 1f57a8e..e416faa 100644 --- a/adapter/handlebars/handlebars.go +++ b/adapter/handlebars/handlebars.go @@ -2,20 +2,18 @@ package handlebars import ( "html" - "log" - "os" "path/filepath" "github.com/aymerick/raymond" "github.com/mickael-menu/zk/adapter/handlebars/helpers" + "github.com/mickael-menu/zk/util" + "github.com/mickael-menu/zk/util/date" "github.com/mickael-menu/zk/util/errors" ) -func Init() { - // FIXME Pass the logger as dependency - logger := log.New(os.Stderr, "zk: warning: ", 0) - // FIXME Support custom languages from the config - helpers.RegisterSlug(logger, "en") +func Init(lang string, logger util.Logger, date date.Provider) { + helpers.RegisterSlug(logger, lang) + helpers.RegisterDate(logger, date) } // HandlebarsRenderer holds parsed handlebars template and renders them. diff --git a/adapter/handlebars/handlebars_test.go b/adapter/handlebars/handlebars_test.go index bfa34da..7c9a848 100644 --- a/adapter/handlebars/handlebars_test.go +++ b/adapter/handlebars/handlebars_test.go @@ -1,14 +1,21 @@ package handlebars import ( + "fmt" + "log" + "os" "testing" + "time" "github.com/mickael-menu/zk/util/assert" + "github.com/mickael-menu/zk/util/date" "github.com/mickael-menu/zk/util/fixtures" ) func init() { - Init() + logger := log.New(os.Stderr, "zk: warning: ", 0) + date := date.NewFrozen(time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)) + Init("en", logger, &date) } func TestRenderString(t *testing.T) { @@ -44,13 +51,34 @@ func TestDoesntEscapeHTML(t *testing.T) { assert.Equal(t, res, "Salut, l'ami!\n") } -func TestSlug(t *testing.T) { +func TestSlugHelper(t *testing.T) { sut := NewRenderer() + // block res, err := sut.Render("{{#slug}}This will be slugified!{{/slug}}", nil) assert.Nil(t, err) assert.Equal(t, res, "this-will-be-slugified") - + // inline res, err = sut.Render(`{{slug "This will be slugified!"}}`, nil) assert.Nil(t, err) assert.Equal(t, res, "this-will-be-slugified") } + +func TestDateHelper(t *testing.T) { + sut := NewRenderer() + + test := func(format string, expected string) { + res, err := sut.Render(fmt.Sprintf("{{date '%s'}}", format), nil) + assert.Nil(t, err) + assert.Equal(t, res, expected) + } + + test("short", "11/17/2009") + test("medium", "Nov 17, 2009") + test("long", "November 17, 2009") + test("full", "Tuesday, November 17, 2009") + test("year", "2009") + test("time", "20:34") + test("timestamp", "200911172034") + test("timestamp-unix", "1258490098") + test("cust: %Y-%m", "cust: 2009-11") +} diff --git a/adapter/handlebars/helpers/date.go b/adapter/handlebars/helpers/date.go new file mode 100644 index 0000000..1d1eb56 --- /dev/null +++ b/adapter/handlebars/helpers/date.go @@ -0,0 +1,54 @@ +package helpers + +import ( + "github.com/aymerick/raymond" + "github.com/lestrrat-go/strftime" + "github.com/mickael-menu/zk/util" + "github.com/mickael-menu/zk/util/date" +) + +func RegisterDate(logger util.Logger, date date.Provider) { + raymond.RegisterHelper("date", func(arg string) string { + format := findFormat(arg) + res, err := strftime.Format(format, date.Date(), strftime.WithUnixSeconds('s')) + if err != nil { + logger.Printf("the {{date}} template helper failed to format the date: %v", err) + return "" + } + return res + }) +} + +var ( + shortFormat = `%m/%d/%Y` + mediumFormat = `%b %d, %Y` + longFormat = `%B %d, %Y` + fullFormat = `%A, %B %d, %Y` + yearFormat = `%Y` + timeFormat = `%H:%M` + timestampFormat = `%Y%m%d%H%M` + timestampUnixFormat = `%s` +) + +func findFormat(key string) string { + switch key { + case "short": + return shortFormat + case "medium": + return mediumFormat + case "long": + return longFormat + case "full": + return fullFormat + case "year": + return yearFormat + case "time": + return timeFormat + case "timestamp": + return timestampFormat + case "timestamp-unix": + return timestampUnixFormat + default: + return key + } +} diff --git a/adapter/handlebars/helpers/slug.go b/adapter/handlebars/helpers/slug.go index c8140fd..9a1ee89 100644 --- a/adapter/handlebars/helpers/slug.go +++ b/adapter/handlebars/helpers/slug.go @@ -6,7 +6,6 @@ import ( "github.com/mickael-menu/zk/util" ) -// FIXME Support custom languages with slug.MakeLang() func RegisterSlug(logger util.Logger, lang string) { raymond.RegisterHelper("slug", func(opt interface{}) string { switch arg := opt.(type) { diff --git a/go.mod b/go.mod index 305a621..aac88d7 100644 --- a/go.mod +++ b/go.mod @@ -8,5 +8,6 @@ require ( github.com/google/go-cmp v0.3.1 github.com/gosimple/slug v1.9.0 github.com/hashicorp/hcl/v2 v2.8.1 + github.com/lestrrat-go/strftime v1.0.3 gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index c9bed9b..78f23d8 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,7 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbj github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= @@ -27,6 +28,9 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/strftime v1.0.3 h1:qqOPU7y+TM8Y803I8fG9c/DyKG3xH/xkng6keC1015Q= +github.com/lestrrat-go/strftime v1.0.3/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -38,8 +42,10 @@ github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDF github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/zclconf/go-cty v1.2.0 h1:sPHsy7ADcIZQP3vILvTjrh74ZA175TFP5vqiNK1UmlI= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= diff --git a/util/date/date.go b/util/date/date.go new file mode 100644 index 0000000..c1afe0a --- /dev/null +++ b/util/date/date.go @@ -0,0 +1,32 @@ +package date + +import "time" + +// Provider returns a date instance. +type Provider interface { + Date() time.Time +} + +// Now is a date provider returning the current date. +type Now struct{} + +func (n *Now) Date() time.Time { + return time.Now() +} + +// Frozen is a date provider returning always the same date. +type Frozen struct { + date time.Time +} + +func NewFrozenNow() Frozen { + return Frozen{time.Now()} +} + +func NewFrozen(date time.Time) Frozen { + return Frozen{date} +} + +func (n *Frozen) Date() time.Time { + return n.date +}