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

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