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 }