summaryrefslogtreecommitdiffstats
path: root/tpl/partials
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-05-01 09:06:42 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-05-01 15:13:41 +0200
commit0e2260421e40c97d9d210724fb44cfdc15ea7855 (patch)
tree13a73d06a67b42584fcd20c08615418e0ec2fe1f /tpl/partials
parent4714085a10835b9f4e8d4f699dc94e3120d8067e (diff)
tpl: Fix the remaining template funcs namespace issues
See #3042
Diffstat (limited to 'tpl/partials')
-rw-r--r--tpl/partials/init.go44
-rw-r--r--tpl/partials/partials.go130
2 files changed, 174 insertions, 0 deletions
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 (ns *Namespace) Foo(i interface{}) {
+
+}
+
+// Include executes the named partial and returns either a string,
+// when the partial is a text/template, or template.HTML when html/template.
+func (ns *Namespace) Include(name string, contextList ...interface{}) (interface{}, error) {
+ if strings.HasPrefix("partials/", name) {
+ name = name[8:]
+ }
+ var context interface{}
+
+ if len(contextList) == 0 {
+ context = nil
+ } else {
+ context = contextList[0]
+ }
+
+ for _, n := range []string{"partials/" + name, "theme/partials/" + name} {
+ templ := ns.deps.Tmpl.Lookup(n)
+ if templ == nil {
+ // For legacy reasons.
+ templ = ns.deps.Tmpl.Lookup(n + ".html")
+ }
+ if templ != nil {
+ b := bp.GetBuffer()
+ defer bp.PutBuffer(b)
+
+ if err := templ.Execute(b, context); err != nil {
+ return "", err
+ }
+
+ if _, ok := templ.Template.(*texttemplate.Template); ok {
+ return b.String(), nil
+ }
+
+ return template.HTML(b.String()), nil
+
+ }
+ }
+
+ return "", fmt.Errorf("Partial %q not found", name)
+}
+
+// getCached executes and caches partial templates. An optional variant
+// string parameter (a string slice actually, but be only use a variadic
+// argument to make it optional) can be passed so that a given partial can have
+// multiple uses. The cache is created with name+variant as the key.
+func (ns *Namespace) getCached(name string, context interface{}, variant ...string) (interface{}, error) {
+ key := name
+ if len(variant) > 0 {
+ for i := 0; i < len(variant); i++ {
+ key += variant[i]
+ }
+ }
+ return ns.getOrCreate(key, name, context)
+}
+
+func (ns *Namespace) getOrCreate(key, name string, context interface{}) (p interface{}, err error) {
+ var ok bool
+
+ ns.cachedPartials.RLock()
+ p, ok = ns.cachedPartials.p[key]
+ ns.cachedPartials.RUnlock()
+
+ if ok {
+ return
+ }
+
+ ns.cachedPartials.Lock()
+ if p, ok = ns.cachedPartials.p[key]; !ok {
+ ns.cachedPartials.Unlock()
+ p, err = ns.Include(name, context)
+
+ ns.cachedPartials.Lock()
+ ns.cachedPartials.p[key] = p
+
+ }
+ ns.cachedPartials.Unlock()
+
+ return
+}