diff --git a/modules/markdown/markdown.go b/modules/markdown/markdown.go index 813fabe1780f..183804a9ee10 100644 --- a/modules/markdown/markdown.go +++ b/modules/markdown/markdown.go @@ -19,6 +19,7 @@ import ( "golang.org/x/net/html" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" ) @@ -40,18 +41,6 @@ func IsMarkdownFile(name string) bool { return false } -// IsReadmeFile reports whether name looks like a README file -// based on its name. -func IsReadmeFile(name string) bool { - name = strings.ToLower(name) - if len(name) < 6 { - return false - } else if len(name) == 6 { - return name == "readme" - } - return name[:7] == "readme." -} - var ( // MentionPattern matches string that mentions someone, e.g. @Unknwon MentionPattern = regexp.MustCompile(`(\s|^|\W)@[0-9a-zA-Z-_\.]+`) @@ -707,3 +696,31 @@ func RenderString(raw, urlPrefix string, metas map[string]string) string { func RenderWiki(rawBytes []byte, urlPrefix string, metas map[string]string) string { return string(render(rawBytes, urlPrefix, metas, true)) } + +var ( + // MarkupName describes markup's name + MarkupName = "markdown" +) + +func init() { + markup.RegisterParser(Parser{}) +} + +// Parser implements markup.Parser +type Parser struct { +} + +// Name implements markup.Parser +func (Parser) Name() string { + return MarkupName +} + +// Extensions implements markup.Parser +func (Parser) Extensions() []string { + return setting.Markdown.FileExtensions +} + +// Render implements markup.Parser +func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte { + return render(rawBytes, urlPrefix, metas, isWiki) +} diff --git a/modules/markdown/markdown_test.go b/modules/markdown/markdown_test.go index 88d289aa0eb0..8364146573f5 100644 --- a/modules/markdown/markdown_test.go +++ b/modules/markdown/markdown_test.go @@ -1,3 +1,7 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + package markdown_test import ( @@ -586,31 +590,6 @@ func TestMisc_IsMarkdownFile(t *testing.T) { } } -func TestMisc_IsReadmeFile(t *testing.T) { - trueTestCases := []string{ - "readme", - "README", - "readME.mdown", - "README.md", - } - falseTestCases := []string{ - "test.md", - "wow.MARKDOWN", - "LOL.mDoWn", - "test", - "abcdefg", - "abcdefghijklmnopqrstuvwxyz", - "test.md.test", - } - - for _, testCase := range trueTestCases { - assert.True(t, IsReadmeFile(testCase)) - } - for _, testCase := range falseTestCases { - assert.False(t, IsReadmeFile(testCase)) - } -} - func TestMisc_IsSameDomain(t *testing.T) { setting.AppURL = AppURL setting.AppSubURL = AppSubURL diff --git a/modules/markup/markup.go b/modules/markup/markup.go new file mode 100644 index 000000000000..0847fcfb0dfe --- /dev/null +++ b/modules/markup/markup.go @@ -0,0 +1,72 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package markup + +import ( + "path/filepath" + "strings" +) + +// Parser defines an interface for parsering markup file to HTML +type Parser interface { + Name() string // markup format name + Extensions() []string + Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte +} + +var ( + parsers = make(map[string]Parser) +) + +// RegisterParser registers a new markup file parser +func RegisterParser(parser Parser) { + for _, ext := range parser.Extensions() { + parsers[strings.ToLower(ext)] = parser + } +} + +// Render renders markup file to HTML with all specific handling stuff. +func Render(filename string, rawBytes []byte, urlPrefix string, metas map[string]string) []byte { + return render(filename, rawBytes, urlPrefix, metas, false) +} + +func render(filename string, rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte { + extension := strings.ToLower(filepath.Ext(filename)) + if parser, ok := parsers[extension]; ok { + return parser.Render(rawBytes, urlPrefix, metas, isWiki) + } + return nil +} + +// RenderString renders Markdown to HTML with special links and returns string type. +func RenderString(filename string, raw, urlPrefix string, metas map[string]string) string { + return string(render(filename, []byte(raw), urlPrefix, metas, false)) +} + +// RenderWiki renders markdown wiki page to HTML and return HTML string +func RenderWiki(filename string, rawBytes []byte, urlPrefix string, metas map[string]string) string { + return string(render(filename, rawBytes, urlPrefix, metas, true)) +} + +// Type returns if markup format via the filename +func Type(filename string) string { + extension := strings.ToLower(filepath.Ext(filename)) + if parser, ok := parsers[extension]; ok { + return parser.Name() + } + return "" +} + +// IsReadmeFile reports whether name looks like a README file +// based on its name. +func IsReadmeFile(name string) bool { + name = strings.ToLower(name) + if len(name) < 6 { + return false + } else if len(name) == 6 { + return name == "readme" + } + return name[:7] == "readme." +} diff --git a/modules/markup/markup_test.go b/modules/markup/markup_test.go new file mode 100644 index 000000000000..92caa8ff9661 --- /dev/null +++ b/modules/markup/markup_test.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package markup + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMisc_IsReadmeFile(t *testing.T) { + trueTestCases := []string{ + "readme", + "README", + "readME.mdown", + "README.md", + } + falseTestCases := []string{ + "test.md", + "wow.MARKDOWN", + "LOL.mDoWn", + "test", + "abcdefg", + "abcdefghijklmnopqrstuvwxyz", + "test.md.test", + } + + for _, testCase := range trueTestCases { + assert.True(t, IsReadmeFile(testCase)) + } + for _, testCase := range falseTestCases { + assert.False(t, IsReadmeFile(testCase)) + } +} diff --git a/routers/repo/view.go b/routers/repo/view.go index 51443a9452ac..2e4b2644cdb0 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -21,7 +21,7 @@ import ( "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/markdown" + "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" "github.com/Unknwon/paginater" @@ -56,7 +56,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { var readmeFile *git.Blob for _, entry := range entries { - if entry.IsDir() || !markdown.IsReadmeFile(entry.Name()) { + if entry.IsDir() || !markup.IsReadmeFile(entry.Name()) { continue } @@ -87,17 +87,16 @@ func renderDirectory(ctx *context.Context, treeLink string) { if isTextFile { d, _ := ioutil.ReadAll(dataRc) buf = append(buf, d...) - switch { - case markdown.IsMarkdownFile(readmeFile.Name()): + newbuf := markup.Render(readmeFile.Name(), buf, treeLink, ctx.Repo.Repository.ComposeMetas()) + if newbuf != nil { ctx.Data["IsMarkdown"] = true - buf = markdown.Render(buf, treeLink, ctx.Repo.Repository.ComposeMetas()) - default: + } else { // FIXME This is the only way to show non-markdown files // instead of a broken "View Raw" link ctx.Data["IsMarkdown"] = true - buf = bytes.Replace(buf, []byte("\n"), []byte(`
`), -1) + newbuf = bytes.Replace(buf, []byte("\n"), []byte(`
`), -1) } - ctx.Data["FileContent"] = string(buf) + ctx.Data["FileContent"] = string(newbuf) } } @@ -182,13 +181,15 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st d, _ := ioutil.ReadAll(dataRc) buf = append(buf, d...) - isMarkdown := markdown.IsMarkdownFile(blob.Name()) - ctx.Data["IsMarkdown"] = isMarkdown + tp := markup.Type(blob.Name()) + isSupportedMarkup := tp != "" + // FIXME: currently set IsMarkdown for compitable + ctx.Data["IsMarkdown"] = isSupportedMarkup - readmeExist := isMarkdown || markdown.IsReadmeFile(blob.Name()) + readmeExist := isSupportedMarkup || markup.IsReadmeFile(blob.Name()) ctx.Data["ReadmeExist"] = readmeExist - if readmeExist && isMarkdown { - ctx.Data["FileContent"] = string(markdown.Render(buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas())) + if readmeExist && isSupportedMarkup { + ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas())) } else { // Building code view blocks with line number on server side. var fileContent string diff --git a/routers/repo/wiki.go b/routers/repo/wiki.go index c1c05d305a37..2dcf37cc869e 100644 --- a/routers/repo/wiki.go +++ b/routers/repo/wiki.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/markdown" + "code.gitea.io/gitea/modules/markup" ) const ( @@ -322,7 +323,7 @@ func Wiki(ctx *context.Context) { } ename := entry.Name() - if !markdown.IsMarkdownFile(ename) { + if markup.Type(ename) != markdown.MarkupName { ext := strings.ToUpper(filepath.Ext(ename)) ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext) }