github.com/whatlly/hugo@v0.47.1/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  	NewTextTemplate() TemplateParseFinder
    42  
    43  	MarkReady()
    44  	RebuildClone()
    45  }
    46  
    47  // TemplateFinder finds templates.
    48  type TemplateFinder interface {
    49  	Lookup(name string) (Template, bool)
    50  }
    51  
    52  // Template is the common interface between text/template and html/template.
    53  type Template interface {
    54  	Execute(wr io.Writer, data interface{}) error
    55  	Name() string
    56  }
    57  
    58  // TemplateParser is used to parse ad-hoc templates, e.g. in the Resource chain.
    59  type TemplateParser interface {
    60  	Parse(name, tpl string) (Template, error)
    61  }
    62  
    63  // TemplateParseFinder provides both parsing and finding.
    64  type TemplateParseFinder interface {
    65  	TemplateParser
    66  	TemplateFinder
    67  }
    68  
    69  // TemplateExecutor adds some extras to Template.
    70  type TemplateExecutor interface {
    71  	Template
    72  	ExecuteToString(data interface{}) (string, error)
    73  	Tree() string
    74  }
    75  
    76  // TemplateDebugger prints some debug info to stdoud.
    77  type TemplateDebugger interface {
    78  	Debug()
    79  }
    80  
    81  // TemplateAdapter implements the TemplateExecutor interface.
    82  type TemplateAdapter struct {
    83  	Template
    84  	Metrics metrics.Provider
    85  }
    86  
    87  // Execute executes the current template. The actual execution is performed
    88  // by the embedded text or html template, but we add an implementation here so
    89  // we can add a timer for some metrics.
    90  func (t *TemplateAdapter) Execute(w io.Writer, data interface{}) error {
    91  	if t.Metrics != nil {
    92  		defer t.Metrics.MeasureSince(t.Name(), time.Now())
    93  	}
    94  	return t.Template.Execute(w, data)
    95  }
    96  
    97  // ExecuteToString executes the current template and returns the result as a
    98  // string.
    99  func (t *TemplateAdapter) ExecuteToString(data interface{}) (string, error) {
   100  	b := bp.GetBuffer()
   101  	defer bp.PutBuffer(b)
   102  	if err := t.Execute(b, data); err != nil {
   103  		return "", err
   104  	}
   105  	return b.String(), nil
   106  }
   107  
   108  // Tree returns the template Parse tree as a string.
   109  // Note: this isn't safe for parallel execution on the same template
   110  // vs Lookup and Execute.
   111  func (t *TemplateAdapter) Tree() string {
   112  	var tree *parse.Tree
   113  	switch tt := t.Template.(type) {
   114  	case *template.Template:
   115  		tree = tt.Tree
   116  	case *texttemplate.Template:
   117  		tree = tt.Tree
   118  	default:
   119  		panic("Unknown template")
   120  	}
   121  
   122  	if tree == nil || tree.Root == nil {
   123  		return ""
   124  	}
   125  	s := tree.Root.String()
   126  
   127  	return s
   128  }
   129  
   130  // TemplateFuncsGetter allows to get a map of functions.
   131  type TemplateFuncsGetter interface {
   132  	GetFuncs() map[string]interface{}
   133  }
   134  
   135  // TemplateTestMocker adds a way to override some template funcs during tests.
   136  // The interface is named so it's not used in regular application code.
   137  type TemplateTestMocker interface {
   138  	SetFuncs(funcMap map[string]interface{})
   139  }