template.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2017 Frédéric Guilloe. 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/config"
  14. "github.com/miniflux/miniflux2/errors"
  15. "github.com/miniflux/miniflux2/locale"
  16. "github.com/miniflux/miniflux2/server/route"
  17. "github.com/miniflux/miniflux2/server/template/helper"
  18. "github.com/miniflux/miniflux2/server/ui/filter"
  19. "github.com/gorilla/mux"
  20. )
  21. // Engine handles the templating system.
  22. type Engine struct {
  23. templates map[string]*template.Template
  24. router *mux.Router
  25. translator *locale.Translator
  26. currentLocale *locale.Language
  27. cfg *config.Config
  28. }
  29. func (e *Engine) parseAll() {
  30. funcMap := template.FuncMap{
  31. "baseURL": func() string {
  32. return e.cfg.Get("BASE_URL", config.DefaultBaseURL)
  33. },
  34. "route": func(name string, args ...interface{}) string {
  35. return route.GetRoute(e.router, name, args...)
  36. },
  37. "noescape": func(str string) template.HTML {
  38. return template.HTML(str)
  39. },
  40. "proxyFilter": func(data string) string {
  41. return filter.ImageProxyFilter(e.router, data)
  42. },
  43. "domain": func(websiteURL string) string {
  44. parsedURL, err := url.Parse(websiteURL)
  45. if err != nil {
  46. return websiteURL
  47. }
  48. return parsedURL.Host
  49. },
  50. "hasPrefix": func(str, prefix string) bool {
  51. return strings.HasPrefix(str, prefix)
  52. },
  53. "contains": func(str, substr string) bool {
  54. return strings.Contains(str, substr)
  55. },
  56. "isodate": func(ts time.Time) string {
  57. return ts.Format("2006-01-02 15:04:05")
  58. },
  59. "elapsed": func(ts time.Time) string {
  60. return helper.GetElapsedTime(e.currentLocale, ts)
  61. },
  62. "t": func(key interface{}, args ...interface{}) string {
  63. switch key.(type) {
  64. case string:
  65. return e.currentLocale.Get(key.(string), args...)
  66. case errors.LocalizedError:
  67. err := key.(errors.LocalizedError)
  68. return err.Localize(e.currentLocale)
  69. case error:
  70. return key.(error).Error()
  71. default:
  72. return ""
  73. }
  74. },
  75. "plural": func(key string, n int, args ...interface{}) string {
  76. return e.currentLocale.Plural(key, n, args...)
  77. },
  78. }
  79. commonTemplates := ""
  80. for _, content := range templateCommonMap {
  81. commonTemplates += content
  82. }
  83. for name, content := range templateViewsMap {
  84. log.Println("Parsing template:", name)
  85. e.templates[name] = template.Must(template.New("main").Funcs(funcMap).Parse(commonTemplates + content))
  86. }
  87. }
  88. // SetLanguage change the language for template processing.
  89. func (e *Engine) SetLanguage(language string) {
  90. e.currentLocale = e.translator.GetLanguage(language)
  91. }
  92. // Execute process a template.
  93. func (e *Engine) Execute(w io.Writer, name string, data interface{}) {
  94. tpl, ok := e.templates[name]
  95. if !ok {
  96. log.Fatalf("The template %s does not exists.\n", name)
  97. }
  98. var b bytes.Buffer
  99. err := tpl.ExecuteTemplate(&b, "base", data)
  100. if err != nil {
  101. log.Fatalf("Unable to render template: %v\n", err)
  102. }
  103. b.WriteTo(w)
  104. }
  105. // NewEngine returns a new template Engine.
  106. func NewEngine(cfg *config.Config, router *mux.Router, translator *locale.Translator) *Engine {
  107. tpl := &Engine{
  108. templates: make(map[string]*template.Template),
  109. router: router,
  110. translator: translator,
  111. cfg: cfg,
  112. }
  113. tpl.parseAll()
  114. return tpl
  115. }