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 7.7 kB

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
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
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
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
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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 base
  5. import (
  6. "bytes"
  7. "container/list"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "html/template"
  12. "runtime"
  13. "strings"
  14. "time"
  15. "github.com/gogits/gogs/modules/mahonia"
  16. "github.com/gogits/gogs/modules/setting"
  17. "github.com/saintfish/chardet"
  18. )
  19. func Str2html(raw string) template.HTML {
  20. return template.HTML(raw)
  21. }
  22. func Range(l int) []int {
  23. return make([]int, l)
  24. }
  25. func List(l *list.List) chan interface{} {
  26. e := l.Front()
  27. c := make(chan interface{})
  28. go func() {
  29. for e != nil {
  30. c <- e.Value
  31. e = e.Next()
  32. }
  33. close(c)
  34. }()
  35. return c
  36. }
  37. func ShortSha(sha1 string) string {
  38. if len(sha1) == 40 {
  39. return sha1[:10]
  40. }
  41. return sha1
  42. }
  43. func ToUtf8WithErr(content []byte) (error, string) {
  44. detector := chardet.NewTextDetector()
  45. result, err := detector.DetectBest(content)
  46. if err != nil {
  47. return err, ""
  48. }
  49. if result.Charset == "utf8" {
  50. return nil, string(content)
  51. }
  52. decoder := mahonia.NewDecoder(result.Charset)
  53. if decoder != nil {
  54. return nil, decoder.ConvertString(string(content))
  55. }
  56. return errors.New("unknow char decoder"), string(content)
  57. }
  58. func ToUtf8(content string) string {
  59. _, res := ToUtf8WithErr([]byte(content))
  60. return res
  61. }
  62. var mailDomains = map[string]string{
  63. "gmail.com": "gmail.com",
  64. }
  65. var TemplateFuncs template.FuncMap = map[string]interface{}{
  66. "GoVer": func() string {
  67. return strings.Title(runtime.Version())
  68. },
  69. "AppName": func() string {
  70. return setting.AppName
  71. },
  72. "AppSubUrl": func() string {
  73. return setting.AppSubUrl
  74. },
  75. "AppVer": func() string {
  76. return setting.AppVer
  77. },
  78. "AppDomain": func() string {
  79. return setting.Domain
  80. },
  81. "CdnMode": func() bool {
  82. return setting.ProdMode && !setting.OfflineMode
  83. },
  84. "LoadTimes": func(startTime time.Time) string {
  85. return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
  86. },
  87. "AvatarLink": AvatarLink,
  88. "str2html": Str2html, // TODO: Legacy
  89. "Str2html": Str2html,
  90. "TimeSince": TimeSince,
  91. "FileSize": FileSize,
  92. "Subtract": Subtract,
  93. "Add": func(a, b int) int {
  94. return a + b
  95. },
  96. "ActionIcon": ActionIcon,
  97. "ActionDesc": ActionDesc,
  98. "DateFormat": DateFormat,
  99. "List": List,
  100. "Mail2Domain": func(mail string) string {
  101. if !strings.Contains(mail, "@") {
  102. return "try.gogits.org"
  103. }
  104. suffix := strings.SplitN(mail, "@", 2)[1]
  105. domain, ok := mailDomains[suffix]
  106. if !ok {
  107. return "mail." + suffix
  108. }
  109. return domain
  110. },
  111. "SubStr": func(str string, start, length int) string {
  112. return str[start : start+length]
  113. },
  114. "DiffTypeToStr": DiffTypeToStr,
  115. "DiffLineTypeToStr": DiffLineTypeToStr,
  116. "ShortSha": ShortSha,
  117. "Md5": EncodeMd5,
  118. "ActionContent2Commits": ActionContent2Commits,
  119. "Oauth2Icon": Oauth2Icon,
  120. "Oauth2Name": Oauth2Name,
  121. "ToUtf8": ToUtf8,
  122. }
  123. type Actioner interface {
  124. GetOpType() int
  125. GetActUserName() string
  126. GetActEmail() string
  127. GetRepoUserName() string
  128. GetRepoName() string
  129. GetBranch() string
  130. GetContent() string
  131. }
  132. // ActionIcon accepts a int that represents action operation type
  133. // and returns a icon class name.
  134. func ActionIcon(opType int) string {
  135. switch opType {
  136. case 1: // Create repository.
  137. return "repo"
  138. case 5, 9: // Commit repository.
  139. return "git-commit"
  140. case 6: // Create issue.
  141. return "issue-opened"
  142. case 8: // Transfer repository.
  143. return "share"
  144. case 10: // Comment issue.
  145. return "comment"
  146. default:
  147. return "invalid type"
  148. }
  149. }
  150. // TODO: Legacy
  151. const (
  152. TPL_CREATE_REPO = `<a href="%s/user/%s">%s</a> created repository <a href="%s">%s</a>`
  153. TPL_COMMIT_REPO = `<a href="%s/user/%s">%s</a> pushed to <a href="%s/src/%s">%s</a> at <a href="%s">%s</a>%s`
  154. TPL_COMMIT_REPO_LI = `<div><img src="%s?s=16" alt="user-avatar"/> <a href="%s/commit/%s" rel="nofollow">%s</a> %s</div>`
  155. TPL_CREATE_ISSUE = `<a href="%s/user/%s">%s</a> opened issue <a href="%s/issues/%s">%s#%s</a>
  156. <div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
  157. TPL_TRANSFER_REPO = `<a href="%s/user/%s">%s</a> transfered repository <code>%s</code> to <a href="%s">%s</a>`
  158. TPL_PUSH_TAG = `<a href="%s/user/%s">%s</a> pushed tag <a href="%s/src/%s" rel="nofollow">%s</a> at <a href="%s">%s</a>`
  159. TPL_COMMENT_ISSUE = `<a href="%s/user/%s">%s</a> commented on issue <a href="%s/issues/%s">%s#%s</a>
  160. <div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
  161. )
  162. type PushCommit struct {
  163. Sha1 string
  164. Message string
  165. AuthorEmail string
  166. AuthorName string
  167. }
  168. type PushCommits struct {
  169. Len int
  170. Commits []*PushCommit
  171. }
  172. func ActionContent2Commits(act Actioner) *PushCommits {
  173. var push *PushCommits
  174. if err := json.Unmarshal([]byte(act.GetContent()), &push); err != nil {
  175. return nil
  176. }
  177. return push
  178. }
  179. // TODO: Legacy
  180. // ActionDesc accepts int that represents action operation type
  181. // and returns the description.
  182. func ActionDesc(act Actioner) string {
  183. actUserName := act.GetActUserName()
  184. email := act.GetActEmail()
  185. repoUserName := act.GetRepoUserName()
  186. repoName := act.GetRepoName()
  187. repoLink := repoUserName + "/" + repoName
  188. branch := act.GetBranch()
  189. content := act.GetContent()
  190. switch act.GetOpType() {
  191. case 1: // Create repository.
  192. return fmt.Sprintf(TPL_CREATE_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, repoName)
  193. case 5: // Commit repository.
  194. var push *PushCommits
  195. if err := json.Unmarshal([]byte(content), &push); err != nil {
  196. return err.Error()
  197. }
  198. buf := bytes.NewBuffer([]byte("\n"))
  199. for _, commit := range push.Commits {
  200. buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, AvatarLink(commit.AuthorEmail), repoLink, commit.Sha1, commit.Sha1[:7], commit.Message) + "\n")
  201. }
  202. if push.Len > 3 {
  203. buf.WriteString(fmt.Sprintf(`<div><a href="{{AppRootSubUrl}}/%s/%s/commits/%s" rel="nofollow">%d other commits >></a></div>`, actUserName, repoName, branch, push.Len))
  204. }
  205. return fmt.Sprintf(TPL_COMMIT_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink,
  206. buf.String())
  207. case 6: // Create issue.
  208. infos := strings.SplitN(content, "|", 2)
  209. return fmt.Sprintf(TPL_CREATE_ISSUE, setting.AppSubUrl, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
  210. AvatarLink(email), infos[1])
  211. case 8: // Transfer repository.
  212. newRepoLink := content + "/" + repoName
  213. return fmt.Sprintf(TPL_TRANSFER_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, newRepoLink, newRepoLink)
  214. case 9: // Push tag.
  215. return fmt.Sprintf(TPL_PUSH_TAG, setting.AppSubUrl, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink)
  216. case 10: // Comment issue.
  217. infos := strings.SplitN(content, "|", 2)
  218. return fmt.Sprintf(TPL_COMMENT_ISSUE, setting.AppSubUrl, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
  219. AvatarLink(email), infos[1])
  220. default:
  221. return "invalid type"
  222. }
  223. }
  224. func DiffTypeToStr(diffType int) string {
  225. diffTypes := map[int]string{
  226. 1: "add", 2: "modify", 3: "del",
  227. }
  228. return diffTypes[diffType]
  229. }
  230. func DiffLineTypeToStr(diffType int) string {
  231. switch diffType {
  232. case 2:
  233. return "add"
  234. case 3:
  235. return "del"
  236. case 4:
  237. return "tag"
  238. }
  239. return "same"
  240. }
  241. func Oauth2Icon(t int) string {
  242. switch t {
  243. case 1:
  244. return "fa-github-square"
  245. case 2:
  246. return "fa-google-plus-square"
  247. case 3:
  248. return "fa-twitter-square"
  249. case 4:
  250. return "fa-qq"
  251. case 5:
  252. return "fa-weibo"
  253. }
  254. return ""
  255. }
  256. func Oauth2Name(t int) string {
  257. switch t {
  258. case 1:
  259. return "GitHub"
  260. case 2:
  261. return "Google+"
  262. case 3:
  263. return "Twitter"
  264. case 4:
  265. return "腾讯 QQ"
  266. case 5:
  267. return "Weibo"
  268. }
  269. return ""
  270. }