template.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright 2017 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package template
  5. import (
  6. "bytes"
  7. "html/template"
  8. "io"
  9. "log"
  10. "net/url"
  11. "strings"
  12. "time"
  13. "github.com/miniflux/miniflux2/errors"
  14. "github.com/miniflux/miniflux2/locale"
  15. "github.com/miniflux/miniflux2/server/route"
  16. "github.com/miniflux/miniflux2/server/template/helper"
  17. "github.com/miniflux/miniflux2/server/ui/filter"
  18. "github.com/gorilla/mux"
  19. )
  20. type TemplateEngine struct {
  21. templates map[string]*template.Template
  22. router *mux.Router
  23. translator *locale.Translator
  24. currentLocale *locale.Language
  25. }
  26. func (t *TemplateEngine) ParseAll() {
  27. funcMap := template.FuncMap{
  28. "route": func(name string, args ...interface{}) string {
  29. return route.GetRoute(t.router, name, args...)
  30. },
  31. "noescape": func(str string) template.HTML {
  32. return template.HTML(str)
  33. },
  34. "proxyFilter": func(data string) string {
  35. return filter.ImageProxyFilter(t.router, data)
  36. },
  37. "domain": func(websiteURL string) string {
  38. parsedURL, err := url.Parse(websiteURL)
  39. if err != nil {
  40. return websiteURL
  41. }
  42. return parsedURL.Host
  43. },
  44. "hasPrefix": func(str, prefix string) bool {
  45. return strings.HasPrefix(str, prefix)
  46. },
  47. "contains": func(str, substr string) bool {
  48. return strings.Contains(str, substr)
  49. },
  50. "isodate": func(ts time.Time) string {
  51. return ts.Format("2006-01-02 15:04:05")
  52. },
  53. "elapsed": func(ts time.Time) string {
  54. return helper.GetElapsedTime(t.currentLocale, ts)
  55. },
  56. "t": func(key interface{}, args ...interface{}) string {
  57. switch key.(type) {
  58. case string:
  59. return t.currentLocale.Get(key.(string), args...)
  60. case errors.LocalizedError:
  61. err := key.(errors.LocalizedError)
  62. return err.Localize(t.currentLocale)
  63. case error:
  64. return key.(error).Error()
  65. default:
  66. return ""
  67. }
  68. },
  69. "plural": func(key string, n int, args ...interface{}) string {
  70. return t.currentLocale.Plural(key, n, args...)
  71. },
  72. }
  73. commonTemplates := ""
  74. for _, content := range templateCommonMap {
  75. commonTemplates += content
  76. }
  77. for name, content := range templateViewsMap {
  78. log.Println("Parsing template:", name)
  79. t.templates[name] = template.Must(template.New("main").Funcs(funcMap).Parse(commonTemplates + content))
  80. }
  81. }
  82. func (t *TemplateEngine) SetLanguage(language string) {
  83. t.currentLocale = t.translator.GetLanguage(language)
  84. }
  85. func (t *TemplateEngine) Execute(w io.Writer, name string, data interface{}) {
  86. tpl, ok := t.templates[name]
  87. if !ok {
  88. log.Fatalf("The template %s does not exists.\n", name)
  89. }
  90. var b bytes.Buffer
  91. err := tpl.ExecuteTemplate(&b, "base", data)
  92. if err != nil {
  93. log.Fatalf("Unable to render template: %v\n", err)
  94. }
  95. b.WriteTo(w)
  96. }
  97. func NewTemplateEngine(router *mux.Router, translator *locale.Translator) *TemplateEngine {
  98. tpl := &TemplateEngine{
  99. templates: make(map[string]*template.Template),
  100. router: router,
  101. translator: translator,
  102. }
  103. tpl.ParseAll()
  104. return tpl
  105. }