template.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package template
  5. import (
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "path/filepath"
  10. "sync"
  11. "text/template"
  12. "text/template/parse"
  13. )
  14. // Template is a specialized Template from "text/template" that produces a safe
  15. // HTML document fragment.
  16. type Template struct {
  17. // Sticky error if escaping fails.
  18. escapeErr error
  19. // We could embed the text/template field, but it's safer not to because
  20. // we need to keep our version of the name space and the underlying
  21. // template's in sync.
  22. text *template.Template
  23. // The underlying template's parse tree, updated to be HTML-safe.
  24. Tree *parse.Tree
  25. *nameSpace // common to all associated templates
  26. }
  27. // escapeOK is a sentinel value used to indicate valid escaping.
  28. var escapeOK = fmt.Errorf("template escaped correctly")
  29. // nameSpace is the data structure shared by all templates in an association.
  30. type nameSpace struct {
  31. mu sync.Mutex
  32. set map[string]*Template
  33. }
  34. // Templates returns a slice of the templates associated with t, including t
  35. // itself.
  36. func (t *Template) Templates() []*Template {
  37. ns := t.nameSpace
  38. ns.mu.Lock()
  39. defer ns.mu.Unlock()
  40. // Return a slice so we don't expose the map.
  41. m := make([]*Template, 0, len(ns.set))
  42. for _, v := range ns.set {
  43. m = append(m, v)
  44. }
  45. return m
  46. }
  47. // escape escapes all associated templates.
  48. func (t *Template) escape() error {
  49. t.nameSpace.mu.Lock()
  50. defer t.nameSpace.mu.Unlock()
  51. if t.escapeErr == nil {
  52. if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
  53. return err
  54. }
  55. } else if t.escapeErr != escapeOK {
  56. return t.escapeErr
  57. }
  58. return nil
  59. }
  60. // Execute applies a parsed template to the specified data object,
  61. // writing the output to wr.
  62. // If an error occurs executing the template or writing its output,
  63. // execution stops, but partial results may already have been written to
  64. // the output writer.
  65. // A template may be executed safely in parallel.
  66. func (t *Template) Execute(wr io.Writer, data interface{}) error {
  67. if err := t.escape(); err != nil {
  68. return err
  69. }
  70. return t.text.Execute(wr, data)
  71. }
  72. // ExecuteTemplate applies the template associated with t that has the given
  73. // name to the specified data object and writes the output to wr.
  74. // If an error occurs executing the template or writing its output,
  75. // execution stops, but partial results may already have been written to
  76. // the output writer.
  77. // A template may be executed safely in parallel.
  78. func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
  79. tmpl, err := t.lookupAndEscapeTemplate(name)
  80. if err != nil {
  81. return err
  82. }
  83. return tmpl.text.Execute(wr, data)
  84. }
  85. // lookupAndEscapeTemplate guarantees that the template with the given name
  86. // is escaped, or returns an error if it cannot be. It returns the named
  87. // template.
  88. func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
  89. t.nameSpace.mu.Lock()
  90. defer t.nameSpace.mu.Unlock()
  91. tmpl = t.set[name]
  92. if tmpl == nil {
  93. return nil, fmt.Errorf("html/template: %q is undefined", name)
  94. }
  95. if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
  96. return nil, tmpl.escapeErr
  97. }
  98. if tmpl.text.Tree == nil || tmpl.text.Root == nil {
  99. return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
  100. }
  101. if t.text.Lookup(name) == nil {
  102. panic("html/template internal error: template escaping out of sync")
  103. }
  104. if tmpl.escapeErr == nil {
  105. err = escapeTemplate(tmpl, tmpl.text.Root, name)
  106. }
  107. return tmpl, err
  108. }
  109. // Parse parses a string into a template. Nested template definitions
  110. // will be associated with the top-level template t. Parse may be
  111. // called multiple times to parse definitions of templates to associate
  112. // with t. It is an error if a resulting template is non-empty (contains
  113. // content other than template definitions) and would replace a
  114. // non-empty template with the same name. (In multiple calls to Parse
  115. // with the same receiver template, only one call can contain text
  116. // other than space, comments, and template definitions.)
  117. func (t *Template) Parse(src string) (*Template, error) {
  118. t.nameSpace.mu.Lock()
  119. t.escapeErr = nil
  120. t.nameSpace.mu.Unlock()
  121. ret, err := t.text.Parse(src)
  122. if err != nil {
  123. return nil, err
  124. }
  125. // In general, all the named templates might have changed underfoot.
  126. // Regardless, some new ones may have been defined.
  127. // The template.Template set has been updated; update ours.
  128. t.nameSpace.mu.Lock()
  129. defer t.nameSpace.mu.Unlock()
  130. for _, v := range ret.Templates() {
  131. name := v.Name()
  132. tmpl := t.set[name]
  133. if tmpl == nil {
  134. tmpl = t.new(name)
  135. }
  136. // Restore our record of this text/template to its unescaped original state.
  137. tmpl.escapeErr = nil
  138. tmpl.text = v
  139. tmpl.Tree = v.Tree
  140. }
  141. return t, nil
  142. }
  143. // AddParseTree creates a new template with the name and parse tree
  144. // and associates it with t.
  145. //
  146. // It returns an error if t has already been executed.
  147. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
  148. t.nameSpace.mu.Lock()
  149. defer t.nameSpace.mu.Unlock()
  150. if t.escapeErr != nil {
  151. return nil, fmt.Errorf("html/template: cannot AddParseTree to %q after it has executed", t.Name())
  152. }
  153. text, err := t.text.AddParseTree(name, tree)
  154. if err != nil {
  155. return nil, err
  156. }
  157. ret := &Template{
  158. nil,
  159. text,
  160. text.Tree,
  161. t.nameSpace,
  162. }
  163. t.set[name] = ret
  164. return ret, nil
  165. }
  166. // Clone returns a duplicate of the template, including all associated
  167. // templates. The actual representation is not copied, but the name space of
  168. // associated templates is, so further calls to Parse in the copy will add
  169. // templates to the copy but not to the original. Clone can be used to prepare
  170. // common templates and use them with variant definitions for other templates
  171. // by adding the variants after the clone is made.
  172. //
  173. // It returns an error if t has already been executed.
  174. func (t *Template) Clone() (*Template, error) {
  175. t.nameSpace.mu.Lock()
  176. defer t.nameSpace.mu.Unlock()
  177. if t.escapeErr != nil {
  178. return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
  179. }
  180. textClone, err := t.text.Clone()
  181. if err != nil {
  182. return nil, err
  183. }
  184. ret := &Template{
  185. nil,
  186. textClone,
  187. textClone.Tree,
  188. &nameSpace{
  189. set: make(map[string]*Template),
  190. },
  191. }
  192. for _, x := range textClone.Templates() {
  193. name := x.Name()
  194. src := t.set[name]
  195. if src == nil || src.escapeErr != nil {
  196. return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
  197. }
  198. x.Tree = x.Tree.Copy()
  199. ret.set[name] = &Template{
  200. nil,
  201. x,
  202. x.Tree,
  203. ret.nameSpace,
  204. }
  205. }
  206. return ret, nil
  207. }
  208. // New allocates a new HTML template with the given name.
  209. func New(name string) *Template {
  210. tmpl := &Template{
  211. nil,
  212. template.New(name),
  213. nil,
  214. &nameSpace{
  215. set: make(map[string]*Template),
  216. },
  217. }
  218. tmpl.set[name] = tmpl
  219. return tmpl
  220. }
  221. // New allocates a new HTML template associated with the given one
  222. // and with the same delimiters. The association, which is transitive,
  223. // allows one template to invoke another with a {{template}} action.
  224. func (t *Template) New(name string) *Template {
  225. t.nameSpace.mu.Lock()
  226. defer t.nameSpace.mu.Unlock()
  227. return t.new(name)
  228. }
  229. // new is the implementation of New, without the lock.
  230. func (t *Template) new(name string) *Template {
  231. tmpl := &Template{
  232. nil,
  233. t.text.New(name),
  234. nil,
  235. t.nameSpace,
  236. }
  237. tmpl.set[name] = tmpl
  238. return tmpl
  239. }
  240. // Name returns the name of the template.
  241. func (t *Template) Name() string {
  242. return t.text.Name()
  243. }
  244. // FuncMap is the type of the map defining the mapping from names to
  245. // functions. Each function must have either a single return value, or two
  246. // return values of which the second has type error. In that case, if the
  247. // second (error) argument evaluates to non-nil during execution, execution
  248. // terminates and Execute returns that error. FuncMap has the same base type
  249. // as FuncMap in "text/template", copied here so clients need not import
  250. // "text/template".
  251. type FuncMap map[string]interface{}
  252. // Funcs adds the elements of the argument map to the template's function map.
  253. // It panics if a value in the map is not a function with appropriate return
  254. // type. However, it is legal to overwrite elements of the map. The return
  255. // value is the template, so calls can be chained.
  256. func (t *Template) Funcs(funcMap FuncMap) *Template {
  257. t.text.Funcs(template.FuncMap(funcMap))
  258. return t
  259. }
  260. // Delims sets the action delimiters to the specified strings, to be used in
  261. // subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
  262. // definitions will inherit the settings. An empty delimiter stands for the
  263. // corresponding default: {{ or }}.
  264. // The return value is the template, so calls can be chained.
  265. func (t *Template) Delims(left, right string) *Template {
  266. t.text.Delims(left, right)
  267. return t
  268. }
  269. // Lookup returns the template with the given name that is associated with t,
  270. // or nil if there is no such template.
  271. func (t *Template) Lookup(name string) *Template {
  272. t.nameSpace.mu.Lock()
  273. defer t.nameSpace.mu.Unlock()
  274. return t.set[name]
  275. }
  276. // Must is a helper that wraps a call to a function returning (*Template, error)
  277. // and panics if the error is non-nil. It is intended for use in variable initializations
  278. // such as
  279. // var t = template.Must(template.New("name").Parse("html"))
  280. func Must(t *Template, err error) *Template {
  281. if err != nil {
  282. panic(err)
  283. }
  284. return t
  285. }
  286. // ParseFiles creates a new Template and parses the template definitions from
  287. // the named files. The returned template's name will have the (base) name and
  288. // (parsed) contents of the first file. There must be at least one file.
  289. // If an error occurs, parsing stops and the returned *Template is nil.
  290. func ParseFiles(filenames ...string) (*Template, error) {
  291. return parseFiles(nil, filenames...)
  292. }
  293. // ParseFiles parses the named files and associates the resulting templates with
  294. // t. If an error occurs, parsing stops and the returned template is nil;
  295. // otherwise it is t. There must be at least one file.
  296. func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
  297. return parseFiles(t, filenames...)
  298. }
  299. // parseFiles is the helper for the method and function. If the argument
  300. // template is nil, it is created from the first file.
  301. func parseFiles(t *Template, filenames ...string) (*Template, error) {
  302. if len(filenames) == 0 {
  303. // Not really a problem, but be consistent.
  304. return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
  305. }
  306. for _, filename := range filenames {
  307. b, err := ioutil.ReadFile(filename)
  308. if err != nil {
  309. return nil, err
  310. }
  311. s := string(b)
  312. name := filepath.Base(filename)
  313. // First template becomes return value if not already defined,
  314. // and we use that one for subsequent New calls to associate
  315. // all the templates together. Also, if this file has the same name
  316. // as t, this file becomes the contents of t, so
  317. // t, err := New(name).Funcs(xxx).ParseFiles(name)
  318. // works. Otherwise we create a new template associated with t.
  319. var tmpl *Template
  320. if t == nil {
  321. t = New(name)
  322. }
  323. if name == t.Name() {
  324. tmpl = t
  325. } else {
  326. tmpl = t.New(name)
  327. }
  328. _, err = tmpl.Parse(s)
  329. if err != nil {
  330. return nil, err
  331. }
  332. }
  333. return t, nil
  334. }
  335. // ParseGlob creates a new Template and parses the template definitions from the
  336. // files identified by the pattern, which must match at least one file. The
  337. // returned template will have the (base) name and (parsed) contents of the
  338. // first file matched by the pattern. ParseGlob is equivalent to calling
  339. // ParseFiles with the list of files matched by the pattern.
  340. func ParseGlob(pattern string) (*Template, error) {
  341. return parseGlob(nil, pattern)
  342. }
  343. // ParseGlob parses the template definitions in the files identified by the
  344. // pattern and associates the resulting templates with t. The pattern is
  345. // processed by filepath.Glob and must match at least one file. ParseGlob is
  346. // equivalent to calling t.ParseFiles with the list of files matched by the
  347. // pattern.
  348. func (t *Template) ParseGlob(pattern string) (*Template, error) {
  349. return parseGlob(t, pattern)
  350. }
  351. // parseGlob is the implementation of the function and method ParseGlob.
  352. func parseGlob(t *Template, pattern string) (*Template, error) {
  353. filenames, err := filepath.Glob(pattern)
  354. if err != nil {
  355. return nil, err
  356. }
  357. if len(filenames) == 0 {
  358. return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
  359. }
  360. return parseFiles(t, filenames...)
  361. }