gview.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. // Package gview implements a template engine based on text/template.
  7. //
  8. // Reserved template variable names:
  9. // I18nLanguage: Assign this variable to define i18n language for each page.
  10. package gview
  11. import (
  12. "context"
  13. "github.com/gogf/gf/container/gmap"
  14. "github.com/gogf/gf/internal/intlog"
  15. "github.com/gogf/gf"
  16. "github.com/gogf/gf/container/garray"
  17. "github.com/gogf/gf/os/gcmd"
  18. "github.com/gogf/gf/os/gfile"
  19. "github.com/gogf/gf/os/glog"
  20. )
  21. // View object for template engine.
  22. type View struct {
  23. paths *garray.StrArray // Searching array for path, NOT concurrent-safe for performance purpose.
  24. data map[string]interface{} // Global template variables.
  25. funcMap map[string]interface{} // Global template function map.
  26. fileCacheMap *gmap.StrAnyMap // File cache map.
  27. config Config // Extra configuration for the view.
  28. }
  29. type (
  30. Params = map[string]interface{} // Params is type for template params.
  31. FuncMap = map[string]interface{} // FuncMap is type for custom template functions.
  32. )
  33. const (
  34. commandEnvKeyForPath = "gf.gview.path"
  35. )
  36. var (
  37. // Default view object.
  38. defaultViewObj *View
  39. )
  40. // checkAndInitDefaultView checks and initializes the default view object.
  41. // The default view object will be initialized just once.
  42. func checkAndInitDefaultView() {
  43. if defaultViewObj == nil {
  44. defaultViewObj = New()
  45. }
  46. }
  47. // ParseContent parses the template content directly using the default view object
  48. // and returns the parsed content.
  49. func ParseContent(ctx context.Context, content string, params ...Params) (string, error) {
  50. checkAndInitDefaultView()
  51. return defaultViewObj.ParseContent(ctx, content, params...)
  52. }
  53. // New returns a new view object.
  54. // The parameter `path` specifies the template directory path to load template files.
  55. func New(path ...string) *View {
  56. view := &View{
  57. paths: garray.NewStrArray(),
  58. data: make(map[string]interface{}),
  59. funcMap: make(map[string]interface{}),
  60. fileCacheMap: gmap.NewStrAnyMap(true),
  61. config: DefaultConfig(),
  62. }
  63. if len(path) > 0 && len(path[0]) > 0 {
  64. if err := view.SetPath(path[0]); err != nil {
  65. intlog.Error(context.TODO(), err)
  66. }
  67. } else {
  68. // Customized dir path from env/cmd.
  69. if envPath := gcmd.GetOptWithEnv(commandEnvKeyForPath).String(); envPath != "" {
  70. if gfile.Exists(envPath) {
  71. if err := view.SetPath(envPath); err != nil {
  72. intlog.Error(context.TODO(), err)
  73. }
  74. } else {
  75. if errorPrint() {
  76. glog.Errorf("Template directory path does not exist: %s", envPath)
  77. }
  78. }
  79. } else {
  80. // Dir path of working dir.
  81. if err := view.SetPath(gfile.Pwd()); err != nil {
  82. intlog.Error(context.TODO(), err)
  83. }
  84. // Dir path of binary.
  85. if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
  86. if err := view.AddPath(selfPath); err != nil {
  87. intlog.Error(context.TODO(), err)
  88. }
  89. }
  90. // Dir path of main package.
  91. if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
  92. if err := view.AddPath(mainPath); err != nil {
  93. intlog.Error(context.TODO(), err)
  94. }
  95. }
  96. }
  97. }
  98. view.SetDelimiters("{{", "}}")
  99. // default build-in variables.
  100. view.data["GF"] = map[string]interface{}{
  101. "version": gf.VERSION,
  102. }
  103. // default build-in functions.
  104. view.BindFuncMap(FuncMap{
  105. "eq": view.buildInFuncEq,
  106. "ne": view.buildInFuncNe,
  107. "lt": view.buildInFuncLt,
  108. "le": view.buildInFuncLe,
  109. "gt": view.buildInFuncGt,
  110. "ge": view.buildInFuncGe,
  111. "text": view.buildInFuncText,
  112. "html": view.buildInFuncHtmlEncode,
  113. "htmlencode": view.buildInFuncHtmlEncode,
  114. "htmldecode": view.buildInFuncHtmlDecode,
  115. "encode": view.buildInFuncHtmlEncode,
  116. "decode": view.buildInFuncHtmlDecode,
  117. "url": view.buildInFuncUrlEncode,
  118. "urlencode": view.buildInFuncUrlEncode,
  119. "urldecode": view.buildInFuncUrlDecode,
  120. "date": view.buildInFuncDate,
  121. "substr": view.buildInFuncSubStr,
  122. "strlimit": view.buildInFuncStrLimit,
  123. "concat": view.buildInFuncConcat,
  124. "replace": view.buildInFuncReplace,
  125. "compare": view.buildInFuncCompare,
  126. "hidestr": view.buildInFuncHideStr,
  127. "highlight": view.buildInFuncHighlight,
  128. "toupper": view.buildInFuncToUpper,
  129. "tolower": view.buildInFuncToLower,
  130. "nl2br": view.buildInFuncNl2Br,
  131. "include": view.buildInFuncInclude,
  132. "dump": view.buildInFuncDump,
  133. "map": view.buildInFuncMap,
  134. "maps": view.buildInFuncMaps,
  135. "json": view.buildInFuncJson,
  136. "plus": view.buildInFuncPlus,
  137. "minus": view.buildInFuncMinus,
  138. "times": view.buildInFuncTimes,
  139. "divide": view.buildInFuncDivide,
  140. })
  141. return view
  142. }