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.

117 lines
3.6 KiB

  1. // Copyright 2017 The Gitea 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 markup
  5. import (
  6. "path/filepath"
  7. "strings"
  8. )
  9. // Init initialize regexps for markdown parsing
  10. func Init() {
  11. getIssueFullPattern()
  12. NewSanitizer()
  13. }
  14. // Parser defines an interface for parsering markup file to HTML
  15. type Parser interface {
  16. Name() string // markup format name
  17. Extensions() []string
  18. Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte
  19. }
  20. var (
  21. extParsers = make(map[string]Parser)
  22. parsers = make(map[string]Parser)
  23. )
  24. // RegisterParser registers a new markup file parser
  25. func RegisterParser(parser Parser) {
  26. parsers[parser.Name()] = parser
  27. for _, ext := range parser.Extensions() {
  28. extParsers[strings.ToLower(ext)] = parser
  29. }
  30. }
  31. // GetParserByFileName get parser by filename
  32. func GetParserByFileName(filename string) Parser {
  33. extension := strings.ToLower(filepath.Ext(filename))
  34. return extParsers[extension]
  35. }
  36. // GetParserByType returns a parser according type
  37. func GetParserByType(tp string) Parser {
  38. return parsers[tp]
  39. }
  40. // Render renders markup file to HTML with all specific handling stuff.
  41. func Render(filename string, rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
  42. return renderFile(filename, rawBytes, urlPrefix, metas, false)
  43. }
  44. // RenderByType renders markup to HTML with special links and returns string type.
  45. func RenderByType(tp string, rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
  46. return renderByType(tp, rawBytes, urlPrefix, metas, false)
  47. }
  48. // RenderString renders Markdown to HTML with special links and returns string type.
  49. func RenderString(filename string, raw, urlPrefix string, metas map[string]string) string {
  50. return string(renderFile(filename, []byte(raw), urlPrefix, metas, false))
  51. }
  52. // RenderWiki renders markdown wiki page to HTML and return HTML string
  53. func RenderWiki(filename string, rawBytes []byte, urlPrefix string, metas map[string]string) string {
  54. return string(renderFile(filename, rawBytes, urlPrefix, metas, true))
  55. }
  56. func render(parser Parser, rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
  57. urlPrefix = strings.Replace(urlPrefix, " ", "+", -1)
  58. result := parser.Render(rawBytes, urlPrefix, metas, isWiki)
  59. result = PostProcess(result, urlPrefix, metas, isWiki)
  60. return SanitizeBytes(result)
  61. }
  62. func renderByType(tp string, rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
  63. if parser, ok := parsers[tp]; ok {
  64. return render(parser, rawBytes, urlPrefix, metas, isWiki)
  65. }
  66. return nil
  67. }
  68. func renderFile(filename string, rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
  69. extension := strings.ToLower(filepath.Ext(filename))
  70. if parser, ok := extParsers[extension]; ok {
  71. return render(parser, rawBytes, urlPrefix, metas, isWiki)
  72. }
  73. return nil
  74. }
  75. // Type returns if markup format via the filename
  76. func Type(filename string) string {
  77. if parser := GetParserByFileName(filename); parser != nil {
  78. return parser.Name()
  79. }
  80. return ""
  81. }
  82. // IsMarkupFile reports whether file is a markup type file
  83. func IsMarkupFile(name, markup string) bool {
  84. if parser := GetParserByFileName(name); parser != nil {
  85. return parser.Name() == markup
  86. }
  87. return false
  88. }
  89. // IsReadmeFile reports whether name looks like a README file
  90. // based on its name.
  91. func IsReadmeFile(name string) bool {
  92. name = strings.ToLower(name)
  93. if len(name) < 6 {
  94. return false
  95. } else if len(name) == 6 {
  96. return name == "readme"
  97. }
  98. return name[:7] == "readme."
  99. }