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

wiki.go 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package repo
  6. import (
  7. "fmt"
  8. "io/ioutil"
  9. "net/http"
  10. "net/url"
  11. "path/filepath"
  12. "strings"
  13. "code.gitea.io/gitea/models"
  14. "code.gitea.io/gitea/modules/base"
  15. "code.gitea.io/gitea/modules/context"
  16. auth "code.gitea.io/gitea/modules/forms"
  17. "code.gitea.io/gitea/modules/git"
  18. "code.gitea.io/gitea/modules/log"
  19. "code.gitea.io/gitea/modules/markup"
  20. "code.gitea.io/gitea/modules/markup/markdown"
  21. "code.gitea.io/gitea/modules/timeutil"
  22. "code.gitea.io/gitea/modules/util"
  23. "code.gitea.io/gitea/modules/web"
  24. wiki_service "code.gitea.io/gitea/services/wiki"
  25. )
  26. const (
  27. tplWikiStart base.TplName = "repo/wiki/start"
  28. tplWikiView base.TplName = "repo/wiki/view"
  29. tplWikiRevision base.TplName = "repo/wiki/revision"
  30. tplWikiNew base.TplName = "repo/wiki/new"
  31. tplWikiPages base.TplName = "repo/wiki/pages"
  32. )
  33. // MustEnableWiki check if wiki is enabled, if external then redirect
  34. func MustEnableWiki(ctx *context.Context) {
  35. if !ctx.Repo.CanRead(models.UnitTypeWiki) &&
  36. !ctx.Repo.CanRead(models.UnitTypeExternalWiki) {
  37. if log.IsTrace() {
  38. log.Trace("Permission Denied: User %-v cannot read %-v or %-v of repo %-v\n"+
  39. "User in repo has Permissions: %-+v",
  40. ctx.User,
  41. models.UnitTypeWiki,
  42. models.UnitTypeExternalWiki,
  43. ctx.Repo.Repository,
  44. ctx.Repo.Permission)
  45. }
  46. ctx.NotFound("MustEnableWiki", nil)
  47. return
  48. }
  49. unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalWiki)
  50. if err == nil {
  51. ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
  52. return
  53. }
  54. }
  55. // PageMeta wiki page meta information
  56. type PageMeta struct {
  57. Name string
  58. SubURL string
  59. UpdatedUnix timeutil.TimeStamp
  60. }
  61. // findEntryForFile finds the tree entry for a target filepath.
  62. func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) {
  63. entry, err := commit.GetTreeEntryByPath(target)
  64. if err != nil && !git.IsErrNotExist(err) {
  65. return nil, err
  66. }
  67. if entry != nil {
  68. return entry, nil
  69. }
  70. // Then the unescaped, shortest alternative
  71. var unescapedTarget string
  72. if unescapedTarget, err = url.QueryUnescape(target); err != nil {
  73. return nil, err
  74. }
  75. return commit.GetTreeEntryByPath(unescapedTarget)
  76. }
  77. func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
  78. wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath())
  79. if err != nil {
  80. ctx.ServerError("OpenRepository", err)
  81. return nil, nil, err
  82. }
  83. commit, err := wikiRepo.GetBranchCommit("master")
  84. if err != nil {
  85. return wikiRepo, nil, err
  86. }
  87. return wikiRepo, commit, nil
  88. }
  89. // wikiContentsByEntry returns the contents of the wiki page referenced by the
  90. // given tree entry. Writes to ctx if an error occurs.
  91. func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
  92. reader, err := entry.Blob().DataAsync()
  93. if err != nil {
  94. ctx.ServerError("Blob.Data", err)
  95. return nil
  96. }
  97. defer reader.Close()
  98. content, err := ioutil.ReadAll(reader)
  99. if err != nil {
  100. ctx.ServerError("ReadAll", err)
  101. return nil
  102. }
  103. return content
  104. }
  105. // wikiContentsByName returns the contents of a wiki page, along with a boolean
  106. // indicating whether the page exists. Writes to ctx if an error occurs.
  107. func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) {
  108. pageFilename := wiki_service.NameToFilename(wikiName)
  109. entry, err := findEntryForFile(commit, pageFilename)
  110. if err != nil && !git.IsErrNotExist(err) {
  111. ctx.ServerError("findEntryForFile", err)
  112. return nil, nil, "", false
  113. } else if entry == nil {
  114. return nil, nil, "", true
  115. }
  116. return wikiContentsByEntry(ctx, entry), entry, pageFilename, false
  117. }
  118. func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
  119. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  120. if err != nil {
  121. if !git.IsErrNotExist(err) {
  122. ctx.ServerError("GetBranchCommit", err)
  123. }
  124. return nil, nil
  125. }
  126. // Get page list.
  127. entries, err := commit.ListEntries()
  128. if err != nil {
  129. if wikiRepo != nil {
  130. wikiRepo.Close()
  131. }
  132. ctx.ServerError("ListEntries", err)
  133. return nil, nil
  134. }
  135. pages := make([]PageMeta, 0, len(entries))
  136. for _, entry := range entries {
  137. if !entry.IsRegular() {
  138. continue
  139. }
  140. wikiName, err := wiki_service.FilenameToName(entry.Name())
  141. if err != nil {
  142. if models.IsErrWikiInvalidFileName(err) {
  143. continue
  144. }
  145. if wikiRepo != nil {
  146. wikiRepo.Close()
  147. }
  148. ctx.ServerError("WikiFilenameToName", err)
  149. return nil, nil
  150. } else if wikiName == "_Sidebar" || wikiName == "_Footer" {
  151. continue
  152. }
  153. pages = append(pages, PageMeta{
  154. Name: wikiName,
  155. SubURL: wiki_service.NameToSubURL(wikiName),
  156. })
  157. }
  158. ctx.Data["Pages"] = pages
  159. // get requested pagename
  160. pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  161. if len(pageName) == 0 {
  162. pageName = "Home"
  163. }
  164. ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
  165. ctx.Data["old_title"] = pageName
  166. ctx.Data["Title"] = pageName
  167. ctx.Data["title"] = pageName
  168. ctx.Data["RequireHighlightJS"] = true
  169. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  170. data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
  171. if noEntry {
  172. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  173. }
  174. if entry == nil || ctx.Written() {
  175. if wikiRepo != nil {
  176. wikiRepo.Close()
  177. }
  178. return nil, nil
  179. }
  180. sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
  181. if ctx.Written() {
  182. if wikiRepo != nil {
  183. wikiRepo.Close()
  184. }
  185. return nil, nil
  186. }
  187. footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
  188. if ctx.Written() {
  189. if wikiRepo != nil {
  190. wikiRepo.Close()
  191. }
  192. return nil, nil
  193. }
  194. metas := ctx.Repo.Repository.ComposeDocumentMetas()
  195. ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
  196. ctx.Data["sidebarPresent"] = sidebarContent != nil
  197. ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)
  198. ctx.Data["footerPresent"] = footerContent != nil
  199. ctx.Data["footerContent"] = markdown.RenderWiki(footerContent, ctx.Repo.RepoLink, metas)
  200. // get commit count - wiki revisions
  201. commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
  202. ctx.Data["CommitCount"] = commitsCount
  203. return wikiRepo, entry
  204. }
  205. func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
  206. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  207. if err != nil {
  208. if wikiRepo != nil {
  209. wikiRepo.Close()
  210. }
  211. if !git.IsErrNotExist(err) {
  212. ctx.ServerError("GetBranchCommit", err)
  213. }
  214. return nil, nil
  215. }
  216. // get requested pagename
  217. pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  218. if len(pageName) == 0 {
  219. pageName = "Home"
  220. }
  221. ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
  222. ctx.Data["old_title"] = pageName
  223. ctx.Data["Title"] = pageName
  224. ctx.Data["title"] = pageName
  225. ctx.Data["RequireHighlightJS"] = true
  226. ctx.Data["Username"] = ctx.Repo.Owner.Name
  227. ctx.Data["Reponame"] = ctx.Repo.Repository.Name
  228. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  229. data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
  230. if noEntry {
  231. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  232. }
  233. if entry == nil || ctx.Written() {
  234. if wikiRepo != nil {
  235. wikiRepo.Close()
  236. }
  237. return nil, nil
  238. }
  239. ctx.Data["content"] = string(data)
  240. ctx.Data["sidebarPresent"] = false
  241. ctx.Data["sidebarContent"] = ""
  242. ctx.Data["footerPresent"] = false
  243. ctx.Data["footerContent"] = ""
  244. // get commit count - wiki revisions
  245. commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
  246. ctx.Data["CommitCount"] = commitsCount
  247. // get page
  248. page := ctx.QueryInt("page")
  249. if page <= 1 {
  250. page = 1
  251. }
  252. // get Commit Count
  253. commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page)
  254. if err != nil {
  255. if wikiRepo != nil {
  256. wikiRepo.Close()
  257. }
  258. ctx.ServerError("CommitsByFileAndRangeNoFollow", err)
  259. return nil, nil
  260. }
  261. commitsHistory = models.ValidateCommitsWithEmails(commitsHistory)
  262. commitsHistory = models.ParseCommitsWithSignature(commitsHistory, ctx.Repo.Repository)
  263. ctx.Data["Commits"] = commitsHistory
  264. pager := context.NewPagination(int(commitsCount), git.CommitsRangeSize, page, 5)
  265. pager.SetDefaultParams(ctx)
  266. ctx.Data["Page"] = pager
  267. return wikiRepo, entry
  268. }
  269. func renderEditPage(ctx *context.Context) {
  270. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  271. if err != nil {
  272. if wikiRepo != nil {
  273. wikiRepo.Close()
  274. }
  275. if !git.IsErrNotExist(err) {
  276. ctx.ServerError("GetBranchCommit", err)
  277. }
  278. return
  279. }
  280. defer func() {
  281. if wikiRepo != nil {
  282. wikiRepo.Close()
  283. }
  284. }()
  285. // get requested pagename
  286. pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  287. if len(pageName) == 0 {
  288. pageName = "Home"
  289. }
  290. ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
  291. ctx.Data["old_title"] = pageName
  292. ctx.Data["Title"] = pageName
  293. ctx.Data["title"] = pageName
  294. ctx.Data["RequireHighlightJS"] = true
  295. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  296. data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
  297. if noEntry {
  298. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  299. }
  300. if entry == nil || ctx.Written() {
  301. return
  302. }
  303. ctx.Data["content"] = string(data)
  304. ctx.Data["sidebarPresent"] = false
  305. ctx.Data["sidebarContent"] = ""
  306. ctx.Data["footerPresent"] = false
  307. ctx.Data["footerContent"] = ""
  308. }
  309. // Wiki renders single wiki page
  310. func Wiki(ctx *context.Context) {
  311. ctx.Data["PageIsWiki"] = true
  312. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  313. if !ctx.Repo.Repository.HasWiki() {
  314. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  315. ctx.HTML(http.StatusOK, tplWikiStart)
  316. return
  317. }
  318. wikiRepo, entry := renderViewPage(ctx)
  319. if ctx.Written() {
  320. if wikiRepo != nil {
  321. wikiRepo.Close()
  322. }
  323. return
  324. }
  325. defer func() {
  326. if wikiRepo != nil {
  327. wikiRepo.Close()
  328. }
  329. }()
  330. if entry == nil {
  331. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  332. ctx.HTML(http.StatusOK, tplWikiStart)
  333. return
  334. }
  335. wikiPath := entry.Name()
  336. if markup.Type(wikiPath) != markdown.MarkupName {
  337. ext := strings.ToUpper(filepath.Ext(wikiPath))
  338. ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext)
  339. }
  340. // Get last change information.
  341. lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
  342. if err != nil {
  343. ctx.ServerError("GetCommitByPath", err)
  344. return
  345. }
  346. ctx.Data["Author"] = lastCommit.Author
  347. ctx.HTML(http.StatusOK, tplWikiView)
  348. }
  349. // WikiRevision renders file revision list of wiki page
  350. func WikiRevision(ctx *context.Context) {
  351. ctx.Data["PageIsWiki"] = true
  352. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  353. if !ctx.Repo.Repository.HasWiki() {
  354. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  355. ctx.HTML(http.StatusOK, tplWikiStart)
  356. return
  357. }
  358. wikiRepo, entry := renderRevisionPage(ctx)
  359. if ctx.Written() {
  360. if wikiRepo != nil {
  361. wikiRepo.Close()
  362. }
  363. return
  364. }
  365. defer func() {
  366. if wikiRepo != nil {
  367. wikiRepo.Close()
  368. }
  369. }()
  370. if entry == nil {
  371. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  372. ctx.HTML(http.StatusOK, tplWikiStart)
  373. return
  374. }
  375. // Get last change information.
  376. wikiPath := entry.Name()
  377. lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
  378. if err != nil {
  379. ctx.ServerError("GetCommitByPath", err)
  380. return
  381. }
  382. ctx.Data["Author"] = lastCommit.Author
  383. ctx.HTML(http.StatusOK, tplWikiRevision)
  384. }
  385. // WikiPages render wiki pages list page
  386. func WikiPages(ctx *context.Context) {
  387. if !ctx.Repo.Repository.HasWiki() {
  388. ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
  389. return
  390. }
  391. ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
  392. ctx.Data["PageIsWiki"] = true
  393. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  394. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  395. if err != nil {
  396. if wikiRepo != nil {
  397. wikiRepo.Close()
  398. }
  399. return
  400. }
  401. entries, err := commit.ListEntries()
  402. if err != nil {
  403. if wikiRepo != nil {
  404. wikiRepo.Close()
  405. }
  406. ctx.ServerError("ListEntries", err)
  407. return
  408. }
  409. pages := make([]PageMeta, 0, len(entries))
  410. for _, entry := range entries {
  411. if !entry.IsRegular() {
  412. continue
  413. }
  414. c, err := wikiRepo.GetCommitByPath(entry.Name())
  415. if err != nil {
  416. if wikiRepo != nil {
  417. wikiRepo.Close()
  418. }
  419. ctx.ServerError("GetCommit", err)
  420. return
  421. }
  422. wikiName, err := wiki_service.FilenameToName(entry.Name())
  423. if err != nil {
  424. if models.IsErrWikiInvalidFileName(err) {
  425. continue
  426. }
  427. if wikiRepo != nil {
  428. wikiRepo.Close()
  429. }
  430. ctx.ServerError("WikiFilenameToName", err)
  431. return
  432. }
  433. pages = append(pages, PageMeta{
  434. Name: wikiName,
  435. SubURL: wiki_service.NameToSubURL(wikiName),
  436. UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
  437. })
  438. }
  439. ctx.Data["Pages"] = pages
  440. defer func() {
  441. if wikiRepo != nil {
  442. wikiRepo.Close()
  443. }
  444. }()
  445. ctx.HTML(http.StatusOK, tplWikiPages)
  446. }
  447. // WikiRaw outputs raw blob requested by user (image for example)
  448. func WikiRaw(ctx *context.Context) {
  449. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  450. if err != nil {
  451. if wikiRepo != nil {
  452. return
  453. }
  454. }
  455. providedPath := ctx.Params("*")
  456. var entry *git.TreeEntry
  457. if commit != nil {
  458. // Try to find a file with that name
  459. entry, err = findEntryForFile(commit, providedPath)
  460. if err != nil && !git.IsErrNotExist(err) {
  461. ctx.ServerError("findFile", err)
  462. return
  463. }
  464. if entry == nil {
  465. // Try to find a wiki page with that name
  466. if strings.HasSuffix(providedPath, ".md") {
  467. providedPath = providedPath[:len(providedPath)-3]
  468. }
  469. wikiPath := wiki_service.NameToFilename(providedPath)
  470. entry, err = findEntryForFile(commit, wikiPath)
  471. if err != nil && !git.IsErrNotExist(err) {
  472. ctx.ServerError("findFile", err)
  473. return
  474. }
  475. }
  476. }
  477. if entry != nil {
  478. if err = ServeBlob(ctx, entry.Blob()); err != nil {
  479. ctx.ServerError("ServeBlob", err)
  480. }
  481. return
  482. }
  483. ctx.NotFound("findEntryForFile", nil)
  484. }
  485. // NewWiki render wiki create page
  486. func NewWiki(ctx *context.Context) {
  487. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  488. ctx.Data["PageIsWiki"] = true
  489. ctx.Data["RequireSimpleMDE"] = true
  490. if !ctx.Repo.Repository.HasWiki() {
  491. ctx.Data["title"] = "Home"
  492. }
  493. ctx.HTML(http.StatusOK, tplWikiNew)
  494. }
  495. // NewWikiPost response for wiki create request
  496. func NewWikiPost(ctx *context.Context) {
  497. form := web.GetForm(ctx).(*auth.NewWikiForm)
  498. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  499. ctx.Data["PageIsWiki"] = true
  500. ctx.Data["RequireSimpleMDE"] = true
  501. if ctx.HasError() {
  502. ctx.HTML(http.StatusOK, tplWikiNew)
  503. return
  504. }
  505. if util.IsEmptyString(form.Title) {
  506. ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplWikiNew, form)
  507. return
  508. }
  509. wikiName := wiki_service.NormalizeWikiName(form.Title)
  510. if len(form.Message) == 0 {
  511. form.Message = ctx.Tr("repo.editor.add", form.Title)
  512. }
  513. if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil {
  514. if models.IsErrWikiReservedName(err) {
  515. ctx.Data["Err_Title"] = true
  516. ctx.RenderWithErr(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form)
  517. } else if models.IsErrWikiAlreadyExist(err) {
  518. ctx.Data["Err_Title"] = true
  519. ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), tplWikiNew, &form)
  520. } else {
  521. ctx.ServerError("AddWikiPage", err)
  522. }
  523. return
  524. }
  525. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName))
  526. }
  527. // EditWiki render wiki modify page
  528. func EditWiki(ctx *context.Context) {
  529. ctx.Data["PageIsWiki"] = true
  530. ctx.Data["PageIsWikiEdit"] = true
  531. ctx.Data["RequireSimpleMDE"] = true
  532. if !ctx.Repo.Repository.HasWiki() {
  533. ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
  534. return
  535. }
  536. renderEditPage(ctx)
  537. if ctx.Written() {
  538. return
  539. }
  540. ctx.HTML(http.StatusOK, tplWikiNew)
  541. }
  542. // EditWikiPost response for wiki modify request
  543. func EditWikiPost(ctx *context.Context) {
  544. form := web.GetForm(ctx).(*auth.NewWikiForm)
  545. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  546. ctx.Data["PageIsWiki"] = true
  547. ctx.Data["RequireSimpleMDE"] = true
  548. if ctx.HasError() {
  549. ctx.HTML(http.StatusOK, tplWikiNew)
  550. return
  551. }
  552. oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  553. newWikiName := wiki_service.NormalizeWikiName(form.Title)
  554. if len(form.Message) == 0 {
  555. form.Message = ctx.Tr("repo.editor.update", form.Title)
  556. }
  557. if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil {
  558. ctx.ServerError("EditWikiPage", err)
  559. return
  560. }
  561. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName))
  562. }
  563. // DeleteWikiPagePost delete wiki page
  564. func DeleteWikiPagePost(ctx *context.Context) {
  565. wikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  566. if len(wikiName) == 0 {
  567. wikiName = "Home"
  568. }
  569. if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil {
  570. ctx.ServerError("DeleteWikiPage", err)
  571. return
  572. }
  573. ctx.JSON(http.StatusOK, map[string]interface{}{
  574. "redirect": ctx.Repo.RepoLink + "/wiki/",
  575. })
  576. }