markdown.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package base
  5. import (
  6. "bytes"
  7. "path"
  8. "github.com/gogits/gfm"
  9. )
  10. func isletter(c byte) bool {
  11. return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
  12. }
  13. func isalnum(c byte) bool {
  14. return (c >= '0' && c <= '9') || isletter(c)
  15. }
  16. var validLinks = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")}
  17. func isLink(link []byte) bool {
  18. for _, prefix := range validLinks {
  19. if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) {
  20. return true
  21. }
  22. }
  23. return false
  24. }
  25. type CustomRender struct {
  26. gfm.Renderer
  27. urlPrefix string
  28. }
  29. func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
  30. if len(link) > 0 && !isLink(link) {
  31. if link[0] == '#' {
  32. link = append([]byte(options.urlPrefix), link...)
  33. } else {
  34. link = []byte(path.Join(options.urlPrefix, string(link)))
  35. }
  36. }
  37. options.Renderer.Link(out, link, title, content)
  38. }
  39. func RenderMarkdown(rawBytes []byte, urlPrefix string) []byte {
  40. htmlFlags := 0
  41. htmlFlags |= gfm.HTML_USE_XHTML
  42. // htmlFlags |= gfm.HTML_USE_SMARTYPANTS
  43. // htmlFlags |= gfm.HTML_SMARTYPANTS_FRACTIONS
  44. // htmlFlags |= gfm.HTML_SMARTYPANTS_LATEX_DASHES
  45. htmlFlags |= gfm.HTML_SKIP_HTML
  46. htmlFlags |= gfm.HTML_SKIP_STYLE
  47. htmlFlags |= gfm.HTML_SKIP_SCRIPT
  48. htmlFlags |= gfm.HTML_GITHUB_BLOCKCODE
  49. htmlFlags |= gfm.HTML_OMIT_CONTENTS
  50. htmlFlags |= gfm.HTML_COMPLETE_PAGE
  51. renderer := &CustomRender{
  52. Renderer: gfm.HtmlRenderer(htmlFlags, "", ""),
  53. urlPrefix: urlPrefix,
  54. }
  55. // set up the parser
  56. extensions := 0
  57. extensions |= gfm.EXTENSION_NO_INTRA_EMPHASIS
  58. extensions |= gfm.EXTENSION_TABLES
  59. extensions |= gfm.EXTENSION_FENCED_CODE
  60. extensions |= gfm.EXTENSION_AUTOLINK
  61. extensions |= gfm.EXTENSION_STRIKETHROUGH
  62. extensions |= gfm.EXTENSION_HARD_LINE_BREAK
  63. extensions |= gfm.EXTENSION_SPACE_HEADERS
  64. extensions |= gfm.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
  65. body := gfm.Markdown(rawBytes, renderer, extensions)
  66. return body
  67. }