template.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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, or escapeOK if succeeded.
  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. escaped bool
  34. esc escaper
  35. }
  36. // Templates returns a slice of the templates associated with t, including t
  37. // itself.
  38. func (t *Template) Templates() []*Template {
  39. ns := t.nameSpace
  40. ns.mu.Lock()
  41. defer ns.mu.Unlock()
  42. // Return a slice so we don't expose the map.
  43. m := make([]*Template, 0, len(ns.set))
  44. for _, v := range ns.set {
  45. m = append(m, v)
  46. }
  47. return m
  48. }
  49. // Option sets options for the template. Options are described by
  50. // strings, either a simple string or "key=value". There can be at
  51. // most one equals sign in an option string. If the option string
  52. // is unrecognized or otherwise invalid, Option panics.
  53. //
  54. // Known options:
  55. //
  56. // missingkey: Control the behavior during execution if a map is
  57. // indexed with a key that is not present in the map.
  58. // "missingkey=default" or "missingkey=invalid"
  59. // The default behavior: Do nothing and continue execution.
  60. // If printed, the result of the index operation is the string
  61. // "<no value>".
  62. // "missingkey=zero"
  63. // The operation returns the zero value for the map type's element.
  64. // "missingkey=error"
  65. // Execution stops immediately with an error.
  66. //
  67. func (t *Template) Option(opt ...string) *Template {
  68. t.text.Option(opt...)
  69. return t
  70. }
  71. // checkCanParse checks whether it is OK to parse templates.
  72. // If not, it returns an error.
  73. func (t *Template) checkCanParse() error {
  74. if t == nil {
  75. return nil
  76. }
  77. t.nameSpace.mu.Lock()
  78. defer t.nameSpace.mu.Unlock()
  79. if t.nameSpace.escaped {
  80. return fmt.Errorf("html/template: cannot Parse after Execute")
  81. }
  82. return nil
  83. }
  84. // escape escapes all associated templates.
  85. func (t *Template) escape() error {
  86. t.nameSpace.mu.Lock()
  87. defer t.nameSpace.mu.Unlock()
  88. t.nameSpace.escaped = true
  89. if t.escapeErr == nil {
  90. if t.Tree == nil {
  91. return fmt.Errorf("template: %q is an incomplete or empty template", t.Name())
  92. }
  93. if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
  94. return err
  95. }
  96. } else if t.escapeErr != escapeOK {
  97. return t.escapeErr
  98. }
  99. return nil
  100. }
  101. // Execute applies a parsed template to the specified data object,
  102. // writing the output to wr.
  103. // If an error occurs executing the template or writing its output,
  104. // execution stops, but partial results may already have been written to
  105. // the output writer.
  106. // A template may be executed safely in parallel, although if parallel
  107. // executions share a Writer the output may be interleaved.
  108. func (t *Template) Execute(wr io.Writer, data interface{}) error {
  109. if err := t.escape(); err != nil {
  110. return err
  111. }
  112. return t.text.Execute(wr, data)
  113. }
  114. // ExecuteTemplate applies the template associated with t that has the given
  115. // name to the specified data object and writes the output to wr.
  116. // If an error occurs executing the template or writing its output,
  117. // execution stops, but partial results may already have been written to
  118. // the output writer.
  119. // A template may be executed safely in parallel, although if parallel
  120. // executions share a Writer the output may be interleaved.
  121. func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
  122. tmpl, err := t.lookupAndEscapeTemplate(name)
  123. if err != nil {
  124. return err
  125. }
  126. return tmpl.text.Execute(wr, data)
  127. }
  128. // lookupAndEscapeTemplate guarantees that the template with the given name
  129. // is escaped, or returns an error if it cannot be. It returns the named
  130. // template.
  131. func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
  132. t.nameSpace.mu.Lock()
  133. defer t.nameSpace.mu.Unlock()
  134. t.nameSpace.escaped = true
  135. tmpl = t.set[name]
  136. if tmpl == nil {
  137. return nil, fmt.Errorf("html/template: %q is undefined", name)
  138. }
  139. if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
  140. return nil, tmpl.escapeErr
  141. }
  142. if tmpl.text.Tree == nil || tmpl.text.Root == nil {
  143. return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
  144. }
  145. if t.text.Lookup(name) == nil {
  146. panic("html/template internal error: template escaping out of sync")
  147. }
  148. if tmpl.escapeErr == nil {
  149. err = escapeTemplate(tmpl, tmpl.text.Root, name)
  150. }
  151. return tmpl, err
  152. }
  153. // DefinedTemplates returns a string listing the defined templates,
  154. // prefixed by the string "; defined templates are: ". If there are none,
  155. // it returns the empty string. Used to generate an error message.
  156. func (t *Template) DefinedTemplates() string {
  157. return t.text.DefinedTemplates()
  158. }
  159. // Parse parses text as a template body for t.
  160. // Named template definitions ({{define ...}} or {{block ...}} statements) in text
  161. // define additional templates associated with t and are removed from the
  162. // definition of t itself.
  163. //
  164. // Templates can be redefined in successive calls to Parse,
  165. // before the first use of Execute on t or any associated template.
  166. // A template definition with a body containing only white space and comments
  167. // is considered empty and will not replace an existing template's body.
  168. // This allows using Parse to add new named template definitions without
  169. // overwriting the main template body.
  170. func (t *Template) Parse(text string) (*Template, error) {
  171. if err := t.checkCanParse(); err != nil {
  172. return nil, err
  173. }
  174. ret, err := t.text.Parse(text)
  175. if err != nil {
  176. return nil, err
  177. }
  178. // In general, all the named templates might have changed underfoot.
  179. // Regardless, some new ones may have been defined.
  180. // The template.Template set has been updated; update ours.
  181. t.nameSpace.mu.Lock()
  182. defer t.nameSpace.mu.Unlock()
  183. for _, v := range ret.Templates() {
  184. name := v.Name()
  185. tmpl := t.set[name]
  186. if tmpl == nil {
  187. tmpl = t.new(name)
  188. }
  189. tmpl.text = v
  190. tmpl.Tree = v.Tree
  191. }
  192. return t, nil
  193. }
  194. // AddParseTree creates a new template with the name and parse tree
  195. // and associates it with t.
  196. //
  197. // It returns an error if t or any associated template has already been executed.
  198. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
  199. if err := t.checkCanParse(); err != nil {
  200. return nil, err
  201. }
  202. t.nameSpace.mu.Lock()
  203. defer t.nameSpace.mu.Unlock()
  204. text, err := t.text.AddParseTree(name, tree)
  205. if err != nil {
  206. return nil, err
  207. }
  208. ret := &Template{
  209. nil,
  210. text,
  211. text.Tree,
  212. t.nameSpace,
  213. }
  214. t.set[name] = ret
  215. return ret, nil
  216. }
  217. // Clone returns a duplicate of the template, including all associated
  218. // templates. The actual representation is not copied, but the name space of
  219. // associated templates is, so further calls to Parse in the copy will add
  220. // templates to the copy but not to the original. Clone can be used to prepare
  221. // common templates and use them with variant definitions for other templates
  222. // by adding the variants after the clone is made.
  223. //
  224. // It returns an error if t has already been executed.
  225. func (t *Template) Clone() (*Template, error) {
  226. t.nameSpace.mu.Lock()
  227. defer t.nameSpace.mu.Unlock()
  228. if t.escapeErr != nil {
  229. return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
  230. }
  231. textClone, err := t.text.Clone()
  232. if err != nil {
  233. return nil, err
  234. }
  235. ns := &nameSpace{set: make(map[string]*Template)}
  236. ns.esc = makeEscaper(ns)
  237. ret := &Template{
  238. nil,
  239. textClone,
  240. textClone.Tree,
  241. ns,
  242. }
  243. ret.set[ret.Name()] = ret
  244. for _, x := range textClone.Templates() {
  245. name := x.Name()
  246. src := t.set[name]
  247. if src == nil || src.escapeErr != nil {
  248. return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
  249. }
  250. x.Tree = x.Tree.Copy()
  251. ret.set[name] = &Template{
  252. nil,
  253. x,
  254. x.Tree,
  255. ret.nameSpace,
  256. }
  257. }
  258. // Return the template associated with the name of this template.
  259. return ret.set[ret.Name()], nil
  260. }
  261. // New allocates a new HTML template with the given name.
  262. func New(name string) *Template {
  263. ns := &nameSpace{set: make(map[string]*Template)}
  264. ns.esc = makeEscaper(ns)
  265. tmpl := &Template{
  266. nil,
  267. template.New(name),
  268. nil,
  269. ns,
  270. }
  271. tmpl.set[name] = tmpl
  272. return tmpl
  273. }
  274. // New allocates a new HTML template associated with the given one
  275. // and with the same delimiters. The association, which is transitive,
  276. // allows one template to invoke another with a {{template}} action.
  277. func (t *Template) New(name string) *Template {
  278. t.nameSpace.mu.Lock()
  279. defer t.nameSpace.mu.Unlock()
  280. return t.new(name)
  281. }
  282. // new is the implementation of New, without the lock.
  283. func (t *Template) new(name string) *Template {
  284. tmpl := &Template{
  285. nil,
  286. t.text.New(name),
  287. nil,
  288. t.nameSpace,
  289. }
  290. tmpl.set[name] = tmpl
  291. return tmpl
  292. }
  293. // Name returns the name of the template.
  294. func (t *Template) Name() string {
  295. return t.text.Name()
  296. }
  297. // FuncMap is the type of the map defining the mapping from names to
  298. // functions. Each function must have either a single return value, or two
  299. // return values of which the second has type error. In that case, if the
  300. // second (error) argument evaluates to non-nil during execution, execution
  301. // terminates and Execute returns that error. FuncMap has the same base type
  302. // as FuncMap in "text/template", copied here so clients need not import
  303. // "text/template".
  304. type FuncMap map[string]interface{}
  305. // Funcs adds the elements of the argument map to the template's function map.
  306. // It must be called before the template is parsed.
  307. // It panics if a value in the map is not a function with appropriate return
  308. // type. However, it is legal to overwrite elements of the map. The return
  309. // value is the template, so calls can be chained.
  310. func (t *Template) Funcs(funcMap FuncMap) *Template {
  311. t.text.Funcs(template.FuncMap(funcMap))
  312. return t
  313. }
  314. // Delims sets the action delimiters to the specified strings, to be used in
  315. // subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
  316. // definitions will inherit the settings. An empty delimiter stands for the
  317. // corresponding default: {{ or }}.
  318. // The return value is the template, so calls can be chained.
  319. func (t *Template) Delims(left, right string) *Template {
  320. t.text.Delims(left, right)
  321. return t
  322. }
  323. // Lookup returns the template with the given name that is associated with t,
  324. // or nil if there is no such template.
  325. func (t *Template) Lookup(name string) *Template {
  326. t.nameSpace.mu.Lock()
  327. defer t.nameSpace.mu.Unlock()
  328. return t.set[name]
  329. }
  330. // Must is a helper that wraps a call to a function returning (*Template, error)
  331. // and panics if the error is non-nil. It is intended for use in variable initializations
  332. // such as
  333. // var t = template.Must(template.New("name").Parse("html"))
  334. func Must(t *Template, err error) *Template {
  335. if err != nil {
  336. panic(err)
  337. }
  338. return t
  339. }
  340. // ParseFiles creates a new Template and parses the template definitions from
  341. // the named files. The returned template's name will have the (base) name and
  342. // (parsed) contents of the first file. There must be at least one file.
  343. // If an error occurs, parsing stops and the returned *Template is nil.
  344. //
  345. // When parsing multiple files with the same name in different directories,
  346. // the last one mentioned will be the one that results.
  347. // For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
  348. // named "foo", while "a/foo" is unavailable.
  349. func ParseFiles(filenames ...string) (*Template, error) {
  350. return parseFiles(nil, filenames...)
  351. }
  352. // ParseFiles parses the named files and associates the resulting templates with
  353. // t. If an error occurs, parsing stops and the returned template is nil;
  354. // otherwise it is t. There must be at least one file.
  355. //
  356. // When parsing multiple files with the same name in different directories,
  357. // the last one mentioned will be the one that results.
  358. //
  359. // ParseFiles returns an error if t or any associated template has already been executed.
  360. func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
  361. return parseFiles(t, filenames...)
  362. }
  363. // parseFiles is the helper for the method and function. If the argument
  364. // template is nil, it is created from the first file.
  365. func parseFiles(t *Template, filenames ...string) (*Template, error) {
  366. if err := t.checkCanParse(); err != nil {
  367. return nil, err
  368. }
  369. if len(filenames) == 0 {
  370. // Not really a problem, but be consistent.
  371. return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
  372. }
  373. for _, filename := range filenames {
  374. b, err := ioutil.ReadFile(filename)
  375. if err != nil {
  376. return nil, err
  377. }
  378. s := string(b)
  379. name := filepath.Base(filename)
  380. // First template becomes return value if not already defined,
  381. // and we use that one for subsequent New calls to associate
  382. // all the templates together. Also, if this file has the same name
  383. // as t, this file becomes the contents of t, so
  384. // t, err := New(name).Funcs(xxx).ParseFiles(name)
  385. // works. Otherwise we create a new template associated with t.
  386. var tmpl *Template
  387. if t == nil {
  388. t = New(name)
  389. }
  390. if name == t.Name() {
  391. tmpl = t
  392. } else {
  393. tmpl = t.New(name)
  394. }
  395. _, err = tmpl.Parse(s)
  396. if err != nil {
  397. return nil, err
  398. }
  399. }
  400. return t, nil
  401. }
  402. // ParseGlob creates a new Template and parses the template definitions from the
  403. // files identified by the pattern, which must match at least one file. The
  404. // returned template will have the (base) name and (parsed) contents of the
  405. // first file matched by the pattern. ParseGlob is equivalent to calling
  406. // ParseFiles with the list of files matched by the pattern.
  407. //
  408. // When parsing multiple files with the same name in different directories,
  409. // the last one mentioned will be the one that results.
  410. func ParseGlob(pattern string) (*Template, error) {
  411. return parseGlob(nil, pattern)
  412. }
  413. // ParseGlob parses the template definitions in the files identified by the
  414. // pattern and associates the resulting templates with t. The pattern is
  415. // processed by filepath.Glob and must match at least one file. ParseGlob is
  416. // equivalent to calling t.ParseFiles with the list of files matched by the
  417. // pattern.
  418. //
  419. // When parsing multiple files with the same name in different directories,
  420. // the last one mentioned will be the one that results.
  421. //
  422. // ParseGlob returns an error if t or any associated template has already been executed.
  423. func (t *Template) ParseGlob(pattern string) (*Template, error) {
  424. return parseGlob(t, pattern)
  425. }
  426. // parseGlob is the implementation of the function and method ParseGlob.
  427. func parseGlob(t *Template, pattern string) (*Template, error) {
  428. if err := t.checkCanParse(); err != nil {
  429. return nil, err
  430. }
  431. filenames, err := filepath.Glob(pattern)
  432. if err != nil {
  433. return nil, err
  434. }
  435. if len(filenames) == 0 {
  436. return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
  437. }
  438. return parseFiles(t, filenames...)
  439. }
  440. // IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
  441. // and whether the value has a meaningful truth value. This is the definition of
  442. // truth used by if and other such actions.
  443. func IsTrue(val interface{}) (truth, ok bool) {
  444. return template.IsTrue(val)
  445. }