Advertisement
Guest User

Untitled

a guest
Aug 22nd, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.24 KB | None | 0 0
  1. package tpl
  2.  
  3. import (
  4. "io"
  5. "log"
  6. "path/filepath"
  7. "strings"
  8. "text/template"
  9. "time"
  10.  
  11. "github.com/fsnotify/fsnotify"
  12. "github.com/labstack/echo"
  13. )
  14.  
  15. // Renderer is a custom html/template renderer for Echo framework
  16. type Renderer struct {
  17. templates *template.Template
  18. whatchDir string
  19. tempateExt string
  20. }
  21.  
  22. // New constructs a new instance of TplRenderer
  23. func New() *Renderer {
  24. return &Renderer{}
  25. }
  26.  
  27. // Render renders a template document
  28. func (r *Renderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
  29.  
  30. // Add global methods if data is a map
  31. if viewContext, isMap := data.(map[string]interface{}); isMap {
  32. viewContext["reverse"] = c.Echo().Reverse
  33. }
  34. // Hot reload doesn't work correctly with base template
  35. //if r.templates.Lookup("base"+r.tempateExt) != nil {
  36. // t := r.templates.Lookup(name)
  37. // return t.ExecuteTemplate(w, "base", data)
  38. //}
  39. return r.templates.ExecuteTemplate(w, name, data)
  40. }
  41.  
  42. // LoadTemplates finds and loads templates by specified pattern
  43. func (r *Renderer) LoadTemplates(pattern string) {
  44. r.whatchDir = filepath.Dir(pattern) + "/"
  45. r.tempateExt = filepath.Ext(pattern)
  46. if r.whatchDir == ""{
  47. log.Fatal("Template directory not found!")
  48. }
  49. if r.tempateExt == "" {
  50. log.Fatal("Template extension can't be recognized!")
  51. }
  52. log.Print("Directory to watch: ", r.whatchDir)
  53. log.Print("Template file extension: ", r.tempateExt)
  54. r.templates = template.Must(template.ParseGlob(pattern))
  55. }
  56.  
  57. // StartFSWatcher reloads templates on their modification.
  58. // This method should be executed only after LoadTemplates method
  59. // as it uses watchDir and templateExt fields
  60. // which extracted from template pattern.
  61. // Otherwise it terminates an app with log.Fatal()
  62. func (r *Renderer) StartFSWatcher() {
  63. if r.templates == nil {
  64. log.Fatal("StartFSWatcher method should be executed only after LoadTempates method")
  65. }
  66. watcher, err := fsnotify.NewWatcher()
  67. if err != nil {
  68. log.Fatal("Failed to create FS watcher: ", err)
  69. }
  70.  
  71. go func() {
  72. // used as intermediate storage for updated templates
  73. updatedTemplates := map[string]bool{}
  74. tick := time.NewTicker(time.Millisecond * 500)
  75.  
  76. for {
  77. select {
  78. case <-tick.C:
  79. templates := make([]string, 0)
  80. for tp, isUpdated := range updatedTemplates {
  81. if isUpdated {
  82. updatedTemplates[tp] = false
  83. templates = append(templates, tp)
  84. }
  85. }
  86. if len(templates) > 0 {
  87. r.updateTemplates(templates...)
  88. }
  89.  
  90. case event, ok := <-watcher.Events:
  91. if !ok {
  92. return
  93. }
  94. // as jetbrains IDE uses "safe write" it must also catch RENAME
  95. if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Rename == fsnotify.Rename {
  96. // filters template files by extension
  97. if strings.HasSuffix(event.Name, r.tempateExt) {
  98. updatedTemplates[event.Name] = true
  99. }
  100. }
  101. case err, ok := <-watcher.Errors:
  102. if !ok {
  103. return
  104. }
  105. log.Print("Template directory watcher returned error: ", err)
  106. }
  107. }
  108. }()
  109.  
  110. err = watcher.Add(r.whatchDir)
  111. if err != nil {
  112. log.Fatal(err)
  113. }
  114. }
  115.  
  116. // updateTemplates is a helper called by
  117. // a StartWatcher endless loop to reload updated templates
  118. func (r *Renderer) updateTemplates(tpl ...string) {
  119. log.Print("Template has been reloaded:", tpl)
  120. r.templates = template.Must(r.templates.ParseFiles(tpl...))
  121. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement