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 16KB

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