github.com/shohhei1126/hugo@v0.42.2-0.20180623210752-3d5928889ad7/tpl/template.go (about)

     1  // Copyright 2017-present The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package tpl
    15  
    16  import (
    17  	"io"
    18  	"time"
    19  
    20  	"text/template/parse"
    21  
    22  	"html/template"
    23  	texttemplate "text/template"
    24  
    25  	bp "github.com/gohugoio/hugo/bufferpool"
    26  	"github.com/gohugoio/hugo/metrics"
    27  )
    28  
    29  var (
    30  	_ TemplateExecutor = (*TemplateAdapter)(nil)
    31  )
    32  
    33  // TemplateHandler manages the collection of templates.
    34  type TemplateHandler interface {
    35  	TemplateFinder
    36  	AddTemplate(name, tpl string) error
    37  	AddLateTemplate(name, tpl string) error
    38  	LoadTemplates(prefix string)
    39  	PrintErrors()
    40  
    41  	MarkReady()
    42  	RebuildClone()
    43  }
    44  
    45  // TemplateFinder finds templates.
    46  type TemplateFinder interface {
    47  	Lookup(name string) *TemplateAdapter
    48  }
    49  
    50  // Template is the common interface between text/template and html/template.
    51  type Template interface {
    52  	Execute(wr io.Writer, data interface{}) error
    53  	Name() string
    54  }
    55  
    56  // TemplateExecutor adds some extras to Template.
    57  type TemplateExecutor interface {
    58  	Template
    59  	ExecuteToString(data interface{}) (string, error)
    60  	Tree() string
    61  }
    62  
    63  // TemplateDebugger prints some debug info to stdoud.
    64  type TemplateDebugger interface {
    65  	Debug()
    66  }
    67  
    68  // TemplateAdapter implements the TemplateExecutor interface.
    69  type TemplateAdapter struct {
    70  	Template
    71  	Metrics metrics.Provider
    72  }
    73  
    74  // Execute executes the current template. The actual execution is performed
    75  // by the embedded text or html template, but we add an implementation here so
    76  // we can add a timer for some metrics.
    77  func (t *TemplateAdapter) Execute(w io.Writer, data interface{}) error {
    78  	if t.Metrics != nil {
    79  		defer t.Metrics.MeasureSince(t.Name(), time.Now())
    80  	}
    81  	return t.Template.Execute(w, data)
    82  }
    83  
    84  // ExecuteToString executes the current template and returns the result as a
    85  // string.
    86  func (t *TemplateAdapter) ExecuteToString(data interface{}) (string, error) {
    87  	b := bp.GetBuffer()
    88  	defer bp.PutBuffer(b)
    89  	if err := t.Execute(b, data); err != nil {
    90  		return "", err
    91  	}
    92  	return b.String(), nil
    93  }
    94  
    95  // Tree returns the template Parse tree as a string.
    96  // Note: this isn't safe for parallel execution on the same template
    97  // vs Lookup and Execute.
    98  func (t *TemplateAdapter) Tree() string {
    99  	var tree *parse.Tree
   100  	switch tt := t.Template.(type) {
   101  	case *template.Template:
   102  		tree = tt.Tree
   103  	case *texttemplate.Template:
   104  		tree = tt.Tree
   105  	default:
   106  		panic("Unknown template")
   107  	}
   108  
   109  	if tree == nil || tree.Root == nil {
   110  		return ""
   111  	}
   112  	s := tree.Root.String()
   113  
   114  	return s
   115  }
   116  
   117  // TemplateFuncsGetter allows to get a map of functions.
   118  type TemplateFuncsGetter interface {
   119  	GetFuncs() map[string]interface{}
   120  }
   121  
   122  // TemplateTestMocker adds a way to override some template funcs during tests.
   123  // The interface is named so it's not used in regular application code.
   124  type TemplateTestMocker interface {
   125  	SetFuncs(funcMap map[string]interface{})
   126  }