view.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package view
  2. import (
  3. "fmt"
  4. "io"
  5. "path/filepath"
  6. "strings"
  7. "github.com/kataras/iris/context"
  8. )
  9. type (
  10. // Engine is the interface for a compatible Iris view engine.
  11. // It's an alias of context.ViewEngine.
  12. Engine = context.ViewEngine
  13. // EngineFuncer is the interface for a compatible Iris view engine
  14. // which accepts builtin framework functions such as url, urlpath and tr.
  15. // It's an alias of context.ViewEngineFuncer.
  16. EngineFuncer = context.ViewEngineFuncer
  17. )
  18. // View is responsible to
  19. // load the correct templates
  20. // for each of the registered view engines.
  21. type View struct {
  22. engines []Engine
  23. }
  24. // Register registers a view engine.
  25. func (v *View) Register(e Engine) {
  26. v.engines = append(v.engines, e)
  27. }
  28. // Find receives a filename, gets its extension and returns the view engine responsible for that file extension
  29. func (v *View) Find(filename string) Engine {
  30. // Read-Only no locks needed, at serve/runtime-time the library is not supposed to add new view engines
  31. for i, n := 0, len(v.engines); i < n; i++ {
  32. e := v.engines[i]
  33. if strings.HasSuffix(filename, e.Ext()) {
  34. return e
  35. }
  36. }
  37. return nil
  38. }
  39. // Len returns the length of view engines registered so far.
  40. func (v *View) Len() int {
  41. return len(v.engines)
  42. }
  43. // ExecuteWriter calls the correct view Engine's ExecuteWriter func
  44. func (v *View) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
  45. if len(filename) > 2 {
  46. if filename[0] == '/' { // omit first slash
  47. filename = filename[1:]
  48. }
  49. }
  50. e := v.Find(filename)
  51. if e == nil {
  52. return fmt.Errorf("no view engine found for '%s'", filepath.Ext(filename))
  53. }
  54. return e.ExecuteWriter(w, filename, layout, bindingData)
  55. }
  56. // AddFunc adds a function to all registered engines.
  57. // Each template engine that supports functions has its own AddFunc too.
  58. func (v *View) AddFunc(funcName string, funcBody interface{}) {
  59. for i, n := 0, len(v.engines); i < n; i++ {
  60. e := v.engines[i]
  61. if engineFuncer, ok := e.(EngineFuncer); ok {
  62. engineFuncer.AddFunc(funcName, funcBody)
  63. }
  64. }
  65. }
  66. // Load compiles all the registered engines.
  67. func (v *View) Load() error {
  68. for i, n := 0, len(v.engines); i < n; i++ {
  69. e := v.engines[i]
  70. if err := e.Load(); err != nil {
  71. return err
  72. }
  73. }
  74. return nil
  75. }
  76. // NoLayout disables the configuration's layout for a specific execution.
  77. const NoLayout = "iris.nolayout"
  78. // returns empty if it's no layout or empty layout and empty configuration's layout.
  79. func getLayout(layout string, globalLayout string) string {
  80. if layout == NoLayout {
  81. return ""
  82. }
  83. if layout == "" && globalLayout != "" {
  84. return globalLayout
  85. }
  86. return layout
  87. }