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

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