wiki.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright 2015 - Present, The Gogs Authors. All rights reserved.
  2. // Copyright 2018 - Present, Gitote. All rights reserved.
  3. //
  4. // This source code is licensed under the MIT license found in the
  5. // LICENSE file in the root directory of this source tree.
  6. package repo
  7. import (
  8. "gitote/gitote/models"
  9. "gitote/gitote/pkg/context"
  10. "gitote/gitote/pkg/form"
  11. "gitote/gitote/pkg/markup"
  12. "io/ioutil"
  13. "strings"
  14. "time"
  15. "gitlab.com/gitote/git-module"
  16. )
  17. const (
  18. // WikiStartTPL page template
  19. WikiStartTPL = "repo/wiki/start"
  20. // WikiViewTPL page template
  21. WikiViewTPL = "repo/wiki/view"
  22. // WikiNewTPL page template
  23. WikiNewTPL = "repo/wiki/new"
  24. // WikiPagesTPL page template
  25. WikiPagesTPL = "repo/wiki/pages"
  26. )
  27. // MustEnableWiki check if wiki is enabled, if external then redirect
  28. func MustEnableWiki(c *context.Context) {
  29. if !c.Repo.Repository.EnableWiki {
  30. c.Handle(404, "MustEnableWiki", nil)
  31. return
  32. }
  33. if c.Repo.Repository.EnableExternalWiki {
  34. c.Redirect(c.Repo.Repository.ExternalWikiURL)
  35. return
  36. }
  37. }
  38. // PageMeta contains the page meta information
  39. type PageMeta struct {
  40. Name string
  41. URL string
  42. Updated time.Time
  43. }
  44. func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, string) {
  45. wikiRepo, err := git.OpenRepository(c.Repo.Repository.WikiPath())
  46. if err != nil {
  47. c.Handle(500, "OpenRepository", err)
  48. return nil, ""
  49. }
  50. commit, err := wikiRepo.GetBranchCommit("master")
  51. if err != nil {
  52. c.Handle(500, "GetBranchCommit", err)
  53. return nil, ""
  54. }
  55. // Get page list.
  56. if isViewPage {
  57. entries, err := commit.ListEntries()
  58. if err != nil {
  59. c.Handle(500, "ListEntries", err)
  60. return nil, ""
  61. }
  62. pages := make([]PageMeta, 0, len(entries))
  63. for i := range entries {
  64. if entries[i].Type == git.OBJECT_BLOB && strings.HasSuffix(entries[i].Name(), ".md") {
  65. name := strings.TrimSuffix(entries[i].Name(), ".md")
  66. pages = append(pages, PageMeta{
  67. Name: name,
  68. URL: models.ToWikiPageURL(name),
  69. })
  70. }
  71. }
  72. c.Data["Pages"] = pages
  73. }
  74. pageURL := c.Params(":page")
  75. if len(pageURL) == 0 {
  76. pageURL = "Home"
  77. }
  78. c.Data["PageURL"] = pageURL
  79. pageName := models.ToWikiPageName(pageURL)
  80. c.Data["old_title"] = pageName
  81. c.Data["Title"] = pageName
  82. c.Data["title"] = pageName
  83. c.Data["RequireHighlightJS"] = true
  84. blob, err := commit.GetBlobByPath(pageName + ".md")
  85. if err != nil {
  86. if git.IsErrNotExist(err) {
  87. c.Redirect(c.Repo.RepoLink + "/wiki/_pages")
  88. } else {
  89. c.Handle(500, "GetBlobByPath", err)
  90. }
  91. return nil, ""
  92. }
  93. r, err := blob.Data()
  94. if err != nil {
  95. c.Handle(500, "Data", err)
  96. return nil, ""
  97. }
  98. data, err := ioutil.ReadAll(r)
  99. if err != nil {
  100. c.Handle(500, "ReadAll", err)
  101. return nil, ""
  102. }
  103. if isViewPage {
  104. c.Data["content"] = string(markup.Markdown(data, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
  105. } else {
  106. c.Data["content"] = string(data)
  107. }
  108. return wikiRepo, pageName
  109. }
  110. // Wiki renders single wiki page
  111. func Wiki(c *context.Context) {
  112. c.Data["PageIsWiki"] = true
  113. if !c.Repo.Repository.HasWiki() {
  114. c.Data["Title"] = c.Tr("repo.wiki")
  115. c.Data["PageIsRepoWiki"] = true
  116. c.HTML(200, WikiStartTPL)
  117. return
  118. }
  119. wikiRepo, pageName := renderWikiPage(c, true)
  120. if c.Written() {
  121. return
  122. }
  123. // Get last change information.
  124. lastCommit, err := wikiRepo.GetCommitByPath(pageName + ".md")
  125. if err != nil {
  126. c.Handle(500, "GetCommitByPath", err)
  127. return
  128. }
  129. c.Data["Author"] = lastCommit.Author
  130. c.HTML(200, WikiViewTPL)
  131. }
  132. // WikiPages render wiki pages list page
  133. func WikiPages(c *context.Context) {
  134. c.Data["Title"] = c.Tr("repo.wiki.pages")
  135. c.Data["PageIsWiki"] = true
  136. if !c.Repo.Repository.HasWiki() {
  137. c.Redirect(c.Repo.RepoLink + "/wiki")
  138. return
  139. }
  140. wikiRepo, err := git.OpenRepository(c.Repo.Repository.WikiPath())
  141. if err != nil {
  142. c.Handle(500, "OpenRepository", err)
  143. return
  144. }
  145. commit, err := wikiRepo.GetBranchCommit("master")
  146. if err != nil {
  147. c.Handle(500, "GetBranchCommit", err)
  148. return
  149. }
  150. entries, err := commit.ListEntries()
  151. if err != nil {
  152. c.Handle(500, "ListEntries", err)
  153. return
  154. }
  155. pages := make([]PageMeta, 0, len(entries))
  156. for i := range entries {
  157. if entries[i].Type == git.OBJECT_BLOB && strings.HasSuffix(entries[i].Name(), ".md") {
  158. commit, err := wikiRepo.GetCommitByPath(entries[i].Name())
  159. if err != nil {
  160. c.ServerError("GetCommitByPath", err)
  161. return
  162. }
  163. name := strings.TrimSuffix(entries[i].Name(), ".md")
  164. pages = append(pages, PageMeta{
  165. Name: name,
  166. URL: models.ToWikiPageURL(name),
  167. Updated: commit.Author.When,
  168. })
  169. }
  170. }
  171. c.Data["Pages"] = pages
  172. c.HTML(200, WikiPagesTPL)
  173. }
  174. // NewWiki render wiki create page
  175. func NewWiki(c *context.Context) {
  176. c.Data["Title"] = c.Tr("repo.wiki.new_page")
  177. c.Data["PageIsWiki"] = true
  178. c.Data["RequireSimpleMDE"] = true
  179. if !c.Repo.Repository.HasWiki() {
  180. c.Data["title"] = "Home"
  181. }
  182. c.HTML(200, WikiNewTPL)
  183. }
  184. // NewWikiPost creates a new wiki
  185. func NewWikiPost(c *context.Context, f form.NewWiki) {
  186. c.Data["Title"] = c.Tr("repo.wiki.new_page")
  187. c.Data["PageIsWiki"] = true
  188. c.Data["RequireSimpleMDE"] = true
  189. if c.HasError() {
  190. c.HTML(200, WikiNewTPL)
  191. return
  192. }
  193. if err := c.Repo.Repository.AddWikiPage(c.User, f.Title, f.Content, f.Message); err != nil {
  194. if models.IsErrWikiAlreadyExist(err) {
  195. c.Data["Err_Title"] = true
  196. c.RenderWithErr(c.Tr("repo.wiki.page_already_exists"), WikiNewTPL, &f)
  197. } else {
  198. c.Handle(500, "AddWikiPage", err)
  199. }
  200. return
  201. }
  202. c.Redirect(c.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(f.Title)))
  203. }
  204. // EditWiki render wiki modify page
  205. func EditWiki(c *context.Context) {
  206. c.Data["PageIsWiki"] = true
  207. c.Data["PageIsWikiEdit"] = true
  208. c.Data["RequireSimpleMDE"] = true
  209. if !c.Repo.Repository.HasWiki() {
  210. c.Redirect(c.Repo.RepoLink + "/wiki")
  211. return
  212. }
  213. renderWikiPage(c, false)
  214. if c.Written() {
  215. return
  216. }
  217. c.HTML(200, WikiNewTPL)
  218. }
  219. // EditWikiPost edits a wiki
  220. func EditWikiPost(c *context.Context, f form.NewWiki) {
  221. c.Data["Title"] = c.Tr("repo.wiki.new_page")
  222. c.Data["PageIsWiki"] = true
  223. c.Data["RequireSimpleMDE"] = true
  224. if c.HasError() {
  225. c.HTML(200, WikiNewTPL)
  226. return
  227. }
  228. if err := c.Repo.Repository.EditWikiPage(c.User, f.OldTitle, f.Title, f.Content, f.Message); err != nil {
  229. c.Handle(500, "EditWikiPage", err)
  230. return
  231. }
  232. c.Redirect(c.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(f.Title)))
  233. }
  234. // DeleteWikiPagePost deletes a wiki
  235. func DeleteWikiPagePost(c *context.Context) {
  236. pageURL := c.Params(":page")
  237. if len(pageURL) == 0 {
  238. pageURL = "Home"
  239. }
  240. pageName := models.ToWikiPageName(pageURL)
  241. if err := c.Repo.Repository.DeleteWikiPage(c.User, pageName); err != nil {
  242. c.Handle(500, "DeleteWikiPage", err)
  243. return
  244. }
  245. c.JSON(200, map[string]interface{}{
  246. "redirect": c.Repo.RepoLink + "/wiki/",
  247. })
  248. }