A webmail client. Forked from https://git.sr.ht/~migadu/alps
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

103 строки
2.1 KiB

  1. package koushin
  2. import (
  3. "fmt"
  4. "html/template"
  5. "io"
  6. "io/ioutil"
  7. "net/url"
  8. "os"
  9. "github.com/labstack/echo/v4"
  10. )
  11. const themesDir = "public/themes"
  12. type renderer struct {
  13. base *template.Template
  14. themes map[string]*template.Template
  15. defaultTheme string
  16. }
  17. func (r *renderer) Render(w io.Writer, name string, data interface{}, ectx echo.Context) error {
  18. // ectx is the raw *echo.context, not our own *context
  19. ctx := ectx.Get("context").(*context)
  20. for _, plugin := range ctx.server.plugins {
  21. if err := plugin.Inject(name, data); err != nil {
  22. return fmt.Errorf("failed to run plugin '%v': %v", plugin.Name(), err)
  23. }
  24. }
  25. // TODO: per-user theme selection
  26. t := r.base
  27. if r.defaultTheme != "" {
  28. t = r.themes[r.defaultTheme]
  29. }
  30. return t.ExecuteTemplate(w, name, data)
  31. }
  32. func loadTheme(name string, base *template.Template) (*template.Template, error) {
  33. theme, err := base.Clone()
  34. if err != nil {
  35. return nil, err
  36. }
  37. theme, err = theme.ParseGlob("public/themes/" + name + "/*.html")
  38. if err != nil {
  39. return nil, err
  40. }
  41. return theme, nil
  42. }
  43. func loadTemplates(logger echo.Logger, defaultTheme string, plugins []Plugin) (*renderer, error) {
  44. base := template.New("").Funcs(template.FuncMap{
  45. "tuple": func(values ...interface{}) []interface{} {
  46. return values
  47. },
  48. "pathescape": func(s string) string {
  49. return url.PathEscape(s)
  50. },
  51. })
  52. for _, p := range plugins {
  53. base = base.Funcs(p.Filters())
  54. }
  55. base, err := base.ParseGlob("public/*.html")
  56. if err != nil {
  57. return nil, err
  58. }
  59. themes := make(map[string]*template.Template)
  60. files, err := ioutil.ReadDir(themesDir)
  61. if err != nil && !os.IsNotExist(err) {
  62. return nil, err
  63. }
  64. for _, fi := range files {
  65. if !fi.IsDir() {
  66. continue
  67. }
  68. logger.Printf("Loading theme '%v'", fi.Name())
  69. var err error
  70. if themes[fi.Name()], err = loadTheme(fi.Name(), base); err != nil {
  71. return nil, fmt.Errorf("failed to load theme '%v': %v", fi.Name(), err)
  72. }
  73. }
  74. if defaultTheme != "" {
  75. if _, ok := themes[defaultTheme]; !ok {
  76. return nil, fmt.Errorf("failed to find default theme '%v'", defaultTheme)
  77. }
  78. }
  79. return &renderer{
  80. base: base,
  81. themes: themes,
  82. defaultTheme: defaultTheme,
  83. }, nil
  84. }