diff options
41 files changed, 396 insertions, 485 deletions
diff --git a/tpl/cast/cast.go b/tpl/cast/cast.go new file mode 100644 index 000000000..d2dfd745f --- /dev/null +++ b/tpl/cast/cast.go @@ -0,0 +1,35 @@ +// Copyright 2017 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 cast + +import ( + _cast "github.com/spf13/cast" +) + +// New returns a new instance of the cast-namespaced template functions. +func New() *Namespace { + return &Namespace{} +} + +// Namespace provides template functions for the "cast" namespace. +type Namespace struct { +} + +func (ns *Namespace) ToInt(v interface{}) (int, error) { + return _cast.ToIntE(v) +} + +func (ns *Namespace) ToString(v interface{}) (string, error) { + return _cast.ToStringE(v) +} diff --git a/tpl/cast/init.go b/tpl/cast/init.go new file mode 100644 index 000000000..acddaa91a --- /dev/null +++ b/tpl/cast/init.go @@ -0,0 +1,45 @@ +// Copyright 2017 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 cast + +import ( + "github.com/spf13/hugo/deps" + "github.com/spf13/hugo/tpl/internal" +) + +const name = "cast" + +func init() { + f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { + ctx := New() + + examples := [][2]string{ + {`{{ "1234" | int | printf "%T" }}`, `int`}, + {`{{ 1234 | string | printf "%T" }}`, `string`}, + } + + return &internal.TemplateFuncsNamespace{ + Name: name, + Context: func() interface{} { return ctx }, + Aliases: map[string]interface{}{ + "int": ctx.ToInt, + "string": ctx.ToString, + }, + Examples: examples, + } + + } + + internal.AddTemplateFuncsNamespace(f) +} diff --git a/tpl/collections/collections.go b/tpl/collections/collections.go index 86674f423..0843fb7bc 100644 --- a/tpl/collections/collections.go +++ b/tpl/collections/collections.go @@ -39,9 +39,6 @@ type Namespace struct { deps *deps.Deps } -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - // After returns all the items after the first N in a rangeable list. func (ns *Namespace) After(index interface{}, seq interface{}) (interface{}, error) { if index == nil || seq == nil { diff --git a/tpl/collections/collections_test.go b/tpl/collections/collections_test.go index 9d34d3be0..eefbcef6c 100644 --- a/tpl/collections/collections_test.go +++ b/tpl/collections/collections_test.go @@ -29,14 +29,6 @@ import ( type tstNoStringer struct{} -func TestNamespace(t *testing.T) { - t.Parallel() - - ns := New(&deps.Deps{}) - - assert.Equal(t, ns, ns.Namespace(), "object pointers should match") -} - func TestAfter(t *testing.T) { t.Parallel() diff --git a/tpl/collections/init.go b/tpl/collections/init.go index ded7b803c..29f6809c3 100644 --- a/tpl/collections/init.go +++ b/tpl/collections/init.go @@ -25,18 +25,18 @@ func init() { ctx := New(d) examples := [][2]string{ - {`delimit: {{ delimit (slice "A" "B" "C") ", " " and " }}`, `delimit: A, B and C`}, - {`echoParam: {{ echoParam .Params "langCode" }}`, `echoParam: en`}, - {`in: {{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `in: Substring found!`}, + {`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`}, + {`{{ echoParam .Params "langCode" }}`, `en`}, + {`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`}, { - `querify 1: {{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`, - `querify 1: bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`}, + `{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`, + `bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`}, { - `querify 2: <a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`, - `querify 2: <a href="https://www.google.com?page=3&q=test">Search</a>`}, - {`sort: {{ slice "B" "C" "A" | sort }}`, `sort: [A B C]`}, - {`seq: {{ seq 3 }}`, `seq: [1 2 3]`}, - {`union: {{ union (slice 1 2 3) (slice 3 4 5) }}`, `union: [1 2 3 4 5]`}, + `<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`, + `<a href="https://www.google.com?page=3&q=test">Search</a>`}, + {`{{ slice "B" "C" "A" | sort }}`, `[A B C]`}, + {`{{ seq 3 }}`, `[1 2 3]`}, + {`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`}, } return &internal.TemplateFuncsNamespace{ diff --git a/tpl/compare/init.go b/tpl/compare/init.go index d8d30d6f4..bf8227353 100644 --- a/tpl/compare/init.go +++ b/tpl/compare/init.go @@ -25,7 +25,9 @@ func init() { ctx := New() examples := [][2]string{ - {`eq: {{ if eq .Section "blog" }}current{{ end }}`, `eq: current`}, + {`{{ if eq .Section "blog" }}current{{ end }}`, `current`}, + {`{{ "Hugo Rocks!" | default "Hugo Rules!" }}`, `Hugo Rocks!`}, + {`{{ "" | default "Hugo Rules!" }}`, `Hugo Rules!`}, } return &internal.TemplateFuncsNamespace{ diff --git a/tpl/crypto/crypto.go b/tpl/crypto/crypto.go index 207e4df39..7aaa9291e 100644 --- a/tpl/crypto/crypto.go +++ b/tpl/crypto/crypto.go @@ -30,9 +30,6 @@ func New() *Namespace { // Namespace provides template functions for the "crypto" namespace. type Namespace struct{} -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - // MD5 hashes the given input and returns its MD5 checksum. func (ns *Namespace) MD5(in interface{}) (string, error) { conv, err := cast.ToStringE(in) diff --git a/tpl/crypto/crypto_test.go b/tpl/crypto/crypto_test.go index 53b41bd26..1bd919c31 100644 --- a/tpl/crypto/crypto_test.go +++ b/tpl/crypto/crypto_test.go @@ -21,14 +21,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestNamespace(t *testing.T) { - t.Parallel() - - ns := New() - - assert.Equal(t, ns, ns.Namespace(), "object pointers should match") -} - func TestMD5(t *testing.T) { t.Parallel() diff --git a/tpl/crypto/init.go b/tpl/crypto/init.go index 81e9b3a1a..7c1899f88 100644 --- a/tpl/crypto/init.go +++ b/tpl/crypto/init.go @@ -26,6 +26,7 @@ func init() { examples := [][2]string{ {`{{ md5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, + {`{{ crypto.MD5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, {`{{ sha1 "Hello world, gophers!" }}`, `c8b5b0e33d408246e30f53e32b8f7627a7a649d4`}, {`{{ sha256 "Hello world, gophers!" }}`, `6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46`}, } diff --git a/tpl/data/data.go b/tpl/data/data.go index 39cbc9b19..a5bba32c3 100644 --- a/tpl/data/data.go +++ b/tpl/data/data.go @@ -26,6 +26,3 @@ func New(deps *deps.Deps) *Namespace { type Namespace struct { deps *deps.Deps } - -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } diff --git a/tpl/encoding/encoding.go b/tpl/encoding/encoding.go index 311edb209..4b02c426a 100644 --- a/tpl/encoding/encoding.go +++ b/tpl/encoding/encoding.go @@ -29,9 +29,6 @@ func New() *Namespace { // Namespace provides template functions for the "encoding" namespace. type Namespace struct{} -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - // Base64Decode returns the base64 decoding of the given content. func (ns *Namespace) Base64Decode(content interface{}) (string, error) { conv, err := cast.ToStringE(content) diff --git a/tpl/encoding/encoding_test.go b/tpl/encoding/encoding_test.go index d03362866..8242561b6 100644 --- a/tpl/encoding/encoding_test.go +++ b/tpl/encoding/encoding_test.go @@ -25,14 +25,6 @@ import ( type tstNoStringer struct{} -func TestNamespace(t *testing.T) { - t.Parallel() - - ns := New() - - assert.Equal(t, ns, ns.Namespace(), "object pointers should match") -} - func TestBase64Decode(t *testing.T) { t.Parallel() diff --git a/tpl/fmt/fmt.go b/tpl/fmt/fmt.go new file mode 100644 index 000000000..5e320fede --- /dev/null +++ b/tpl/fmt/fmt.go @@ -0,0 +1,39 @@ +// Copyright 2017 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 fmt + +import ( + _fmt "fmt" +) + +// New returns a new instance of the fmt-namespaced template functions. +func New() *Namespace { + return &Namespace{} +} + +// Namespace provides template functions for the "fmt" namespace. +type Namespace struct { +} + +func (ns *Namespace) Print(a ...interface{}) (n int, err error) { + return _fmt.Print(a...) +} + +func (ns *Namespace) Printf(format string, a ...interface{}) (n int, err error) { + return _fmt.Printf(format, a...) +} + +func (ns *Namespace) Println(a ...interface{}) (n int, err error) { + return _fmt.Println(a...) +} diff --git a/tpl/fmt/init.go b/tpl/fmt/init.go new file mode 100644 index 000000000..0f4296263 --- /dev/null +++ b/tpl/fmt/init.go @@ -0,0 +1,43 @@ +// Copyright 2017 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 fmt + +import ( + "github.com/spf13/hugo/deps" + "github.com/spf13/hugo/tpl/internal" +) + +const name = "fmt" + +func init() { + f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { + ctx := New() + + examples := [][2]string{ + {`{{ print "works!" }}`, `works!`}, + {`{{ printf "%s!" "works" }}`, `works!`}, + {`{{ println "works!" }}`, "works!\n"}, + } + + return &internal.TemplateFuncsNamespace{ + Name: name, + Context: func() interface{} { return ctx }, + Aliases: map[string]interface{}{}, + Examples: examples, + } + + } + + internal.AddTemplateFuncsNamespace(f) +} diff --git a/tpl/images/images.go b/tpl/images/images.go index 6700603dd..127057853 100644 --- a/tpl/images/images.go +++ b/tpl/images/images.go @@ -43,9 +43,6 @@ type Namespace struct { deps *deps.Deps } -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - // Config returns the image.Config for the specified path relative to the // working directory. func (ns *Namespace) Config(path interface{}) (image.Config, error) { diff --git a/tpl/images/images_test.go b/tpl/images/images_test.go index 740a469af..964d3fb91 100644 --- a/tpl/images/images_test.go +++ b/tpl/images/images_test.go @@ -80,17 +80,6 @@ var configTests = []struct { {path: "", expect: false}, } -func TestNamespace(t *testing.T) { - t.Parallel() - - v := viper.New() - v.Set("workingDir", "/a/b") - - ns := New(&deps.Deps{Fs: hugofs.NewMem(v)}) - - assert.Equal(t, ns, ns.Namespace(), "object pointers should match") -} - func TestNSConfig(t *testing.T) { t.Parallel() diff --git a/tpl/inflect/inflect.go b/tpl/inflect/inflect.go index 9c13238b5..e66aee72f 100644 --- a/tpl/inflect/inflect.go +++ b/tpl/inflect/inflect.go @@ -28,9 +28,6 @@ func New() *Namespace { // Namespace provides template functions for the "inflect" namespace. type Namespace struct{} -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - // Humanize returns the humanized form of a single parameter. // // If the parameter is either an integer or a string containing an integer diff --git a/tpl/inflect/inflect_test.go b/tpl/inflect/inflect_test.go index 028d5d9af..a2146a838 100644 --- a/tpl/inflect/inflect_test.go +++ b/tpl/inflect/inflect_test.go @@ -8,14 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestNamespace(t *testing.T) { - t.Parallel() - - ns := New() - - assert.Equal(t, ns, ns.Namespace(), "object pointers should match") -} - func TestInflect(t *testing.T) { t.Parallel() diff --git a/tpl/lang/lang.go b/tpl/lang/lang.go index cd6e7c563..c84728f3b 100644 --- a/tpl/lang/lang.go +++ b/tpl/lang/lang.go @@ -30,10 +30,6 @@ type Namespace struct { deps *deps.Deps } -// Namespace returns a pointer to the current namespace instance. -// TODO(bep) namespace remove this and other unused when done. -func (ns *Namespace) Namespace() *Namespace { return ns } - // Translate ... func (ns *Namespace) Translate(id interface{}, args ...interface{}) (string, error) { sid, err := cast.ToStringE(id) diff --git a/tpl/math/math.go b/tpl/math/math.go index 47b7b8306..57e7baf12 100644 --- a/tpl/math/math.go +++ b/tpl/math/math.go @@ -26,9 +26,6 @@ func New() *Namespace { // Namespace provides template functions for the "math" namespace. type Namespace struct{} -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - func (ns *Namespace) Add(a, b interface{}) (interface{}, error) { return DoArithmetic(a, b, '+') } diff --git a/tpl/math/math_test.go b/tpl/math/math_test.go index 649a2756e..40bed5539 100644 --- a/tpl/math/math_test.go +++ b/tpl/math/math_test.go @@ -21,14 +21,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestNamespace(t *testing.T) { - t.Parallel() - - ns := New() - - assert.Equal(t, ns, ns.Namespace(), "object pointers should match") -} - func TestBasicNSArithmetic(t *testing.T) { t.Parallel() diff --git a/tpl/os/init.go b/tpl/os/init.go index 4ab1c56ca..d03ad5f03 100644 --- a/tpl/os/init.go +++ b/tpl/os/init.go @@ -25,7 +25,7 @@ func init() { ctx := New(d) examples := [][2]string{ - {`{{ range (readDir ".") }}{{ .Name }}{{ end }}`, `README.txt`}, + {`{{ range (readDir ".") }}{{ .Name }}{{ end }}`, "README.txt"}, {`{{ readFile "README.txt" }}`, `Hugo Rocks!`}, } diff --git a/tpl/os/os.go b/tpl/os/os.go index 91d6e14f6..03e16e5a9 100644 --- a/tpl/os/os.go +++ b/tpl/os/os.go @@ -35,9 +35,6 @@ type Namespace struct { deps *deps.Deps } -// Namespace returns a pointer to the current namespace instance. -func (ns *Namespace) Namespace() *Namespace { return ns } - // Getenv retrieves the value of the environment variable named by the key. // It returns the value, which will be empty if the variable is not present. func (ns *Namespace) Getenv(key interface{}) (string, error) { diff --git a/tpl/partials/init.go b/tpl/partials/init.go new file mode 100644 index 000000000..a9d1f82fe --- /dev/null +++ b/tpl/partials/init.go @@ -0,0 +1,44 @@ +// Copyright 2017 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 partials + +import ( + "github.com/spf13/hugo/deps" + "github.com/spf13/hugo/tpl/internal" +) + +const name = "partials" + +func init() { + f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { + ctx := New(d) + + examples := [][2]string{ + {`{{ partial "header.html" . }}`, `<title>Hugo Rocks!</title>`}, + } + + return &internal.TemplateFuncsNamespace{ + Name: name, + Context: func() interface{} { return ctx }, + Aliases: map[string]interface{}{ + "partial": ctx.Include, + "partialCached": ctx.getCached, + }, + Examples: examples, + } + + } + + internal.AddTemplateFuncsNamespace(f) +} diff --git a/tpl/partials/partials.go b/tpl/partials/partials.go new file mode 100644 index 000000000..a57edcaec --- /dev/null +++ b/tpl/partials/partials.go @@ -0,0 +1,130 @@ +// Copyright 2017 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 partials + +import ( + "fmt" + "html/template" + "strings" + "sync" + texttemplate "text/template" + + bp "github.com/spf13/hugo/bufferpool" + "github.com/spf13/hugo/deps" +) + +var TestTemplateProvider deps.ResourceProvider + +// partialCache represents a cache of partials protected by a mutex. +type partialCache struct { + sync.RWMutex + p map[string]interface{} +} + +// New returns a new instance of the templates-namespaced template functions. +func New(deps *deps.Deps) *Namespace { + return &Namespace{ + deps: deps, + cachedPartials: partialCache{p: make(map[string]interface{})}, + } +} + +// Namespace provides template functions for the "templates" namespace. +type Namespace struct { + deps *deps.Deps + cachedPartials partialCache +} + +func |