diff --git a/compare/eq.go b/compare/compare.go similarity index 74% rename from compare/eq.go rename to compare/compare.go index 6120c0bf2..19a5deaa2 100644 --- a/compare/eq.go +++ b/compare/compare.go @@ -19,3 +19,11 @@ package compare type Eqer interface { Eq(other interface{}) bool } + +// Comparer can be used to compare two values. +// This will be used when using the le, ge etc. operators in the templates. +// Compare returns -1 if the given version is less than, 0 if equal and 1 if greater than +// the running version. +type Comparer interface { + Compare(other interface{}) int +} diff --git a/helpers/hugo.go b/helpers/hugo.go index c4c3f4a76..b9b42e6cf 100644 --- a/helpers/hugo.go +++ b/helpers/hugo.go @@ -18,6 +18,7 @@ import ( "fmt" "strings" + "github.com/gohugoio/hugo/compare" "github.com/spf13/cast" ) @@ -34,10 +35,40 @@ type HugoVersion struct { Suffix string } +var ( + _ compare.Eqer = (*HugoVersionString)(nil) + _ compare.Comparer = (*HugoVersionString)(nil) +) + +type HugoVersionString string + func (v HugoVersion) String() string { return hugoVersion(v.Number, v.PatchLevel, v.Suffix) } +func (v HugoVersion) Version() HugoVersionString { + return HugoVersionString(v.String()) +} + +func (h HugoVersionString) String() string { + return string(h) +} + +// Implements compare.Comparer +func (h HugoVersionString) Compare(other interface{}) int { + v := MustParseHugoVersion(h.String()) + return compareVersions(v.Number, v.PatchLevel, other) +} + +// Implements compare.Eqer +func (h HugoVersionString) Eq(other interface{}) bool { + s, err := cast.ToStringE(other) + if err != nil { + return false + } + return s == h.String() +} + // ParseHugoVersion parses a version string. func ParseHugoVersion(s string) (HugoVersion, error) { var vv HugoVersion diff --git a/helpers/hugo_test.go b/helpers/hugo_test.go index 1f5e5193f..78742c705 100644 --- a/helpers/hugo_test.go +++ b/helpers/hugo_test.go @@ -29,6 +29,11 @@ func TestHugoVersion(t *testing.T) { require.Equal(t, v.ReleaseVersion().String(), "0.21") require.Equal(t, "0.21-DEV", v.String()) require.Equal(t, "0.22", v.Next().String()) + nextVersionString := v.Next().Version() + require.Equal(t, "0.22", nextVersionString.String()) + require.True(t, nextVersionString.Eq("0.22")) + require.False(t, nextVersionString.Eq("0.21")) + require.True(t, nextVersionString.Eq(nextVersionString)) require.Equal(t, "0.20.3", v.NextPatchLevel(3).String()) } diff --git a/hugolib/hugo_info.go b/hugolib/hugo_info.go index 1e0c192e5..303231edb 100644 --- a/hugolib/hugo_info.go +++ b/hugolib/hugo_info.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Hugo Authors. All rights reserved. +// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ var hugoInfo *HugoInfo // HugoInfo contains information about the current Hugo environment type HugoInfo struct { - Version string + Version helpers.HugoVersionString Generator template.HTML CommitHash string BuildDate string @@ -41,7 +41,7 @@ type HugoInfo struct { func init() { hugoInfo = &HugoInfo{ - Version: helpers.CurrentHugoVersion.String(), + Version: helpers.CurrentHugoVersion.Version(), CommitHash: CommitHash, BuildDate: BuildDate, Generator: template.HTML(fmt.Sprintf(``, helpers.CurrentHugoVersion.String())), diff --git a/hugolib/hugo_info_test.go b/hugolib/hugo_info_test.go new file mode 100644 index 000000000..0a34330ac --- /dev/null +++ b/hugolib/hugo_info_test.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hugolib + +import ( + "fmt" + "testing" + + "github.com/gohugoio/hugo/helpers" + "github.com/stretchr/testify/require" +) + +func TestHugoInfo(t *testing.T) { + assert := require.New(t) + + assert.Equal(helpers.CurrentHugoVersion.Version(), hugoInfo.Version) + assert.IsType(helpers.HugoVersionString(""), hugoInfo.Version) + assert.Equal(CommitHash, hugoInfo.CommitHash) + assert.Equal(BuildDate, hugoInfo.BuildDate) + assert.Contains(hugoInfo.Generator, fmt.Sprintf("Hugo %s", hugoInfo.Version)) + +} diff --git a/tpl/compare/compare.go b/tpl/compare/compare.go index 65228da99..b228040cd 100644 --- a/tpl/compare/compare.go +++ b/tpl/compare/compare.go @@ -88,11 +88,12 @@ func (*Namespace) Default(dflt interface{}, given ...interface{}) (interface{}, // Eq returns the boolean truth of arg1 == arg2. func (*Namespace) Eq(x, y interface{}) bool { - // hugolib.Page implements compare.Eqer to make Page and PageOutput comparable. - if e1, ok := x.(compare.Eqer); ok { - if e2, ok := y.(compare.Eqer); ok { - return e1.Eq(e2) - } + if e, ok := x.(compare.Eqer); ok { + return e.Eq(y) + } + + if e, ok := y.(compare.Eqer); ok { + return e.Eq(x) } normalize := func(v interface{}) interface{} { @@ -120,25 +121,25 @@ func (n *Namespace) Ne(x, y interface{}) bool { // Ge returns the boolean truth of arg1 >= arg2. func (n *Namespace) Ge(a, b interface{}) bool { - left, right := n.compareGetFloat(a, b) + left, right := n.compareGet(a, b) return left >= right } // Gt returns the boolean truth of arg1 > arg2. func (n *Namespace) Gt(a, b interface{}) bool { - left, right := n.compareGetFloat(a, b) + left, right := n.compareGet(a, b) return left > right } // Le returns the boolean truth of arg1 <= arg2. func (n *Namespace) Le(a, b interface{}) bool { - left, right := n.compareGetFloat(a, b) + left, right := n.compareGet(a, b) return left <= right } // Lt returns the boolean truth of arg1 < arg2. func (n *Namespace) Lt(a, b interface{}) bool { - left, right := n.compareGetFloat(a, b) + left, right := n.compareGet(a, b) return left < right } @@ -151,7 +152,29 @@ func (n *Namespace) Conditional(condition bool, a, b interface{}) interface{} { return b } -func (*Namespace) compareGetFloat(a interface{}, b interface{}) (float64, float64) { +func (*Namespace) compareGet(a interface{}, b interface{}) (float64, float64) { + if ac, ok := a.(compare.Comparer); ok { + c := ac.Compare(b) + if c < 0 { + return 1, 0 + } else if c == 0 { + return 0, 0 + } else { + return 0, 1 + } + } + + if bc, ok := b.(compare.Comparer); ok { + c := bc.Compare(a) + if c < 0 { + return 0, 1 + } else if c == 0 { + return 0, 0 + } else { + return 1, 0 + } + } + var left, right float64 var leftStr, rightStr *string av := reflect.ValueOf(a) diff --git a/tpl/compare/compare_test.go b/tpl/compare/compare_test.go index c9bc2ffe9..d201c995b 100644 --- a/tpl/compare/compare_test.go +++ b/tpl/compare/compare_test.go @@ -21,6 +21,8 @@ import ( "testing" "time" + "github.com/gohugoio/hugo/helpers" + "github.com/spf13/cast" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -171,6 +173,13 @@ func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b inte {tstEqerType1("a"), tstEqerType2("a"), 0}, {tstEqerType2("a"), tstEqerType1("a"), 0}, {tstEqerType2("a"), tstEqerType1("b"), -1}, + {helpers.MustParseHugoVersion("0.32.1").Version(), helpers.MustParseHugoVersion("0.32").Version(), 1}, + {helpers.MustParseHugoVersion("0.35").Version(), helpers.MustParseHugoVersion("0.32").Version(), 1}, + {helpers.MustParseHugoVersion("0.36").Version(), helpers.MustParseHugoVersion("0.36").Version(), 0}, + {helpers.MustParseHugoVersion("0.32").Version(), helpers.MustParseHugoVersion("0.36").Version(), -1}, + {helpers.MustParseHugoVersion("0.32").Version(), "0.36", -1}, + {"0.36", helpers.MustParseHugoVersion("0.32").Version(), 1}, + {"0.36", helpers.MustParseHugoVersion("0.36").Version(), 0}, } { result := funcUnderTest(test.left, test.right) success := false diff --git a/tpl/compare/init.go b/tpl/compare/init.go index 7d58cf9ab..f766ef890 100644 --- a/tpl/compare/init.go +++ b/tpl/compare/init.go @@ -46,7 +46,9 @@ func init() { ns.AddMethodMapping(ctx.Ge, []string{"ge"}, - [][2]string{}, + [][2]string{ + {`{{ if ge .Hugo.Version "0.36" }}Reasonable new Hugo version!{{ end }}`, `Reasonable new Hugo version!`}, + }, ) ns.AddMethodMapping(ctx.Gt, diff --git a/tpl/tplimpl/template_funcs_test.go b/tpl/tplimpl/template_funcs_test.go index 32f1a1a71..b8390c5b9 100644 --- a/tpl/tplimpl/template_funcs_test.go +++ b/tpl/tplimpl/template_funcs_test.go @@ -80,12 +80,14 @@ func TestTemplateFuncsExamples(t *testing.T) { var data struct { Title string Section string + Hugo map[string]interface{} Params map[string]interface{} } data.Title = "**BatMan**" data.Section = "blog" data.Params = map[string]interface{}{"langCode": "en"} + data.Hugo = map[string]interface{}{"Version": helpers.MustParseHugoVersion("0.36.1").Version()} for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns := nsf(d)