You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

template.go 5.8 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package template
  5. import (
  6. "container/list"
  7. "encoding/json"
  8. "fmt"
  9. "html/template"
  10. "runtime"
  11. "strings"
  12. "time"
  13. "golang.org/x/net/html/charset"
  14. "golang.org/x/text/transform"
  15. "github.com/gogits/gogs/models"
  16. "github.com/gogits/gogs/modules/base"
  17. "github.com/gogits/gogs/modules/setting"
  18. )
  19. var Funcs template.FuncMap = map[string]interface{}{
  20. "GoVer": func() string {
  21. return strings.Title(runtime.Version())
  22. },
  23. "AppName": func() string {
  24. return setting.AppName
  25. },
  26. "AppSubUrl": func() string {
  27. return setting.AppSubUrl
  28. },
  29. "AppVer": func() string {
  30. return setting.AppVer
  31. },
  32. "AppDomain": func() string {
  33. return setting.Domain
  34. },
  35. "DisableGravatar": func() bool {
  36. return setting.DisableGravatar
  37. },
  38. "LoadTimes": func(startTime time.Time) string {
  39. return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
  40. },
  41. "AvatarLink": base.AvatarLink,
  42. "Safe": Safe,
  43. "Str2html": Str2html,
  44. "TimeSince": base.TimeSince,
  45. "RawTimeSince": base.RawTimeSince,
  46. "FileSize": base.FileSize,
  47. "Subtract": base.Subtract,
  48. "Add": func(a, b int) int {
  49. return a + b
  50. },
  51. "ActionIcon": ActionIcon,
  52. "DateFmtLong": func(t time.Time) string {
  53. return t.Format(time.RFC1123Z)
  54. },
  55. "DateFmtShort": func(t time.Time) string {
  56. return t.Format("Jan 02, 2006")
  57. },
  58. "List": List,
  59. "Mail2Domain": func(mail string) string {
  60. if !strings.Contains(mail, "@") {
  61. return "try.gogs.io"
  62. }
  63. return strings.SplitN(mail, "@", 2)[1]
  64. },
  65. "SubStr": func(str string, start, length int) string {
  66. if len(str) == 0 {
  67. return ""
  68. }
  69. end := start + length
  70. if length == -1 {
  71. end = len(str)
  72. }
  73. if len(str) < end {
  74. return str
  75. }
  76. return str[start:end]
  77. },
  78. "DiffTypeToStr": DiffTypeToStr,
  79. "DiffLineTypeToStr": DiffLineTypeToStr,
  80. "Sha1": Sha1,
  81. "ShortSha": base.ShortSha,
  82. "Md5": base.EncodeMd5,
  83. "ActionContent2Commits": ActionContent2Commits,
  84. "ToUtf8": ToUtf8,
  85. "EscapePound": func(str string) string {
  86. return strings.Replace(strings.Replace(str, "%", "%25", -1), "#", "%23", -1)
  87. },
  88. "RenderCommitMessage": RenderCommitMessage,
  89. }
  90. func Safe(raw string) template.HTML {
  91. return template.HTML(raw)
  92. }
  93. func Str2html(raw string) template.HTML {
  94. return template.HTML(base.Sanitizer.Sanitize(raw))
  95. }
  96. func Range(l int) []int {
  97. return make([]int, l)
  98. }
  99. func List(l *list.List) chan interface{} {
  100. e := l.Front()
  101. c := make(chan interface{})
  102. go func() {
  103. for e != nil {
  104. c <- e.Value
  105. e = e.Next()
  106. }
  107. close(c)
  108. }()
  109. return c
  110. }
  111. func Sha1(str string) string {
  112. return base.EncodeSha1(str)
  113. }
  114. func ToUtf8WithErr(content []byte) (error, string) {
  115. charsetLabel, err := base.DetectEncoding(content)
  116. if err != nil {
  117. return err, ""
  118. }
  119. if charsetLabel == "UTF-8" {
  120. return nil, string(content)
  121. }
  122. encoding, _ := charset.Lookup(charsetLabel)
  123. if encoding == nil {
  124. return fmt.Errorf("unknown char decoder %s", charsetLabel), string(content)
  125. }
  126. result, n, err := transform.String(encoding.NewDecoder(), string(content))
  127. // If there is an error, we concatenate the nicely decoded part and the
  128. // original left over. This way we won't loose data.
  129. if err != nil {
  130. result = result + string(content[n:])
  131. }
  132. return err, result
  133. }
  134. func ToUtf8(content string) string {
  135. _, res := ToUtf8WithErr([]byte(content))
  136. return res
  137. }
  138. // Replaces all prefixes 'old' in 's' with 'new'.
  139. func ReplaceLeft(s, old, new string) string {
  140. old_len, new_len, i, n := len(old), len(new), 0, 0
  141. for ; i < len(s) && strings.HasPrefix(s[i:], old); n += 1 {
  142. i += old_len
  143. }
  144. // simple optimization
  145. if n == 0 {
  146. return s
  147. }
  148. // allocating space for the new string
  149. newLen := n*new_len + len(s[i:])
  150. replacement := make([]byte, newLen, newLen)
  151. j := 0
  152. for ; j < n*new_len; j += new_len {
  153. copy(replacement[j:j+new_len], new)
  154. }
  155. copy(replacement[j:], s[i:])
  156. return string(replacement)
  157. }
  158. // RenderCommitMessage renders commit message with XSS-safe and special links.
  159. func RenderCommitMessage(msg, urlPrefix string) template.HTML {
  160. cleanMsg := template.HTMLEscapeString(msg)
  161. fullMessage := string(base.RenderIssueIndexPattern([]byte(cleanMsg), urlPrefix))
  162. msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n")
  163. for i := range msgLines {
  164. msgLines[i] = ReplaceLeft(msgLines[i], " ", "&nbsp;")
  165. }
  166. fullMessage = strings.Join(msgLines, "<br>")
  167. return template.HTML(fullMessage)
  168. }
  169. type Actioner interface {
  170. GetOpType() int
  171. GetActUserName() string
  172. GetActEmail() string
  173. GetRepoUserName() string
  174. GetRepoName() string
  175. GetRepoPath() string
  176. GetRepoLink() string
  177. GetBranch() string
  178. GetContent() string
  179. GetCreate() time.Time
  180. GetIssueInfos() []string
  181. }
  182. // ActionIcon accepts a int that represents action operation type
  183. // and returns a icon class name.
  184. func ActionIcon(opType int) string {
  185. switch opType {
  186. case 1, 8: // Create, transfer repository
  187. return "repo"
  188. case 5, 9: // Commit repository
  189. return "git-commit"
  190. case 6: // Create issue
  191. return "issue-opened"
  192. case 7: // New pull request
  193. return "git-pull-request"
  194. case 10: // Comment issue
  195. return "comment"
  196. case 11: // Merge pull request
  197. return "git-merge"
  198. default:
  199. return "invalid type"
  200. }
  201. }
  202. func ActionContent2Commits(act Actioner) *models.PushCommits {
  203. push := models.NewPushCommits()
  204. if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil {
  205. return nil
  206. }
  207. return push
  208. }
  209. func DiffTypeToStr(diffType int) string {
  210. diffTypes := map[int]string{
  211. 1: "add", 2: "modify", 3: "del", 4: "rename",
  212. }
  213. return diffTypes[diffType]
  214. }
  215. func DiffLineTypeToStr(diffType int) string {
  216. switch diffType {
  217. case 2:
  218. return "add"
  219. case 3:
  220. return "del"
  221. case 4:
  222. return "tag"
  223. }
  224. return "same"
  225. }