mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 12:03:26 +00:00 
			
		
		
		
	Add markup package to prepare for org markup format (#1493)
This commit is contained in:
		
				
					committed by
					
						 Kim "BKC" Carlbäcker
						Kim "BKC" Carlbäcker
					
				
			
			
				
	
			
			
			
						parent
						
							f0db3da713
						
					
				
				
					commit
					52627032bc
				
			| @@ -19,6 +19,7 @@ import ( | |||||||
| 	"golang.org/x/net/html" | 	"golang.org/x/net/html" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/markup" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -40,18 +41,6 @@ func IsMarkdownFile(name string) bool { | |||||||
| 	return false | 	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 ( | var ( | ||||||
| 	// MentionPattern matches string that mentions someone, e.g. @Unknwon | 	// MentionPattern matches string that mentions someone, e.g. @Unknwon | ||||||
| 	MentionPattern = regexp.MustCompile(`(\s|^|\W)@[0-9a-zA-Z-_\.]+`) | 	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 { | func RenderWiki(rawBytes []byte, urlPrefix string, metas map[string]string) string { | ||||||
| 	return string(render(rawBytes, urlPrefix, metas, true)) | 	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) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -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 | package markdown_test | ||||||
|  |  | ||||||
| import ( | 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) { | func TestMisc_IsSameDomain(t *testing.T) { | ||||||
| 	setting.AppURL = AppURL | 	setting.AppURL = AppURL | ||||||
| 	setting.AppSubURL = AppSubURL | 	setting.AppSubURL = AppSubURL | ||||||
|   | |||||||
							
								
								
									
										72
									
								
								modules/markup/markup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								modules/markup/markup.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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." | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								modules/markup/markup_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								modules/markup/markup_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -21,7 +21,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/highlight" | 	"code.gitea.io/gitea/modules/highlight" | ||||||
| 	"code.gitea.io/gitea/modules/lfs" | 	"code.gitea.io/gitea/modules/lfs" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"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/setting" | ||||||
| 	"code.gitea.io/gitea/modules/templates" | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"github.com/Unknwon/paginater" | 	"github.com/Unknwon/paginater" | ||||||
| @@ -56,7 +56,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { | |||||||
|  |  | ||||||
| 	var readmeFile *git.Blob | 	var readmeFile *git.Blob | ||||||
| 	for _, entry := range entries { | 	for _, entry := range entries { | ||||||
| 		if entry.IsDir() || !markdown.IsReadmeFile(entry.Name()) { | 		if entry.IsDir() || !markup.IsReadmeFile(entry.Name()) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -87,17 +87,16 @@ func renderDirectory(ctx *context.Context, treeLink string) { | |||||||
| 		if isTextFile { | 		if isTextFile { | ||||||
| 			d, _ := ioutil.ReadAll(dataRc) | 			d, _ := ioutil.ReadAll(dataRc) | ||||||
| 			buf = append(buf, d...) | 			buf = append(buf, d...) | ||||||
| 			switch { | 			newbuf := markup.Render(readmeFile.Name(), buf, treeLink, ctx.Repo.Repository.ComposeMetas()) | ||||||
| 			case markdown.IsMarkdownFile(readmeFile.Name()): | 			if newbuf != nil { | ||||||
| 				ctx.Data["IsMarkdown"] = true | 				ctx.Data["IsMarkdown"] = true | ||||||
| 				buf = markdown.Render(buf, treeLink, ctx.Repo.Repository.ComposeMetas()) | 			} else { | ||||||
| 			default: |  | ||||||
| 				// FIXME This is the only way to show non-markdown files | 				// FIXME This is the only way to show non-markdown files | ||||||
| 				// instead of a broken "View Raw" link | 				// instead of a broken "View Raw" link | ||||||
| 				ctx.Data["IsMarkdown"] = true | 				ctx.Data["IsMarkdown"] = true | ||||||
| 				buf = bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1) | 				newbuf = bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -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) | 		d, _ := ioutil.ReadAll(dataRc) | ||||||
| 		buf = append(buf, d...) | 		buf = append(buf, d...) | ||||||
|  |  | ||||||
| 		isMarkdown := markdown.IsMarkdownFile(blob.Name()) | 		tp := markup.Type(blob.Name()) | ||||||
| 		ctx.Data["IsMarkdown"] = isMarkdown | 		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 | 		ctx.Data["ReadmeExist"] = readmeExist | ||||||
| 		if readmeExist && isMarkdown { | 		if readmeExist && isSupportedMarkup { | ||||||
| 			ctx.Data["FileContent"] = string(markdown.Render(buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas())) | 			ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas())) | ||||||
| 		} else { | 		} else { | ||||||
| 			// Building code view blocks with line number on server side. | 			// Building code view blocks with line number on server side. | ||||||
| 			var fileContent string | 			var fileContent string | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/markdown" | 	"code.gitea.io/gitea/modules/markdown" | ||||||
|  | 	"code.gitea.io/gitea/modules/markup" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -322,7 +323,7 @@ func Wiki(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ename := entry.Name() | 	ename := entry.Name() | ||||||
| 	if !markdown.IsMarkdownFile(ename) { | 	if markup.Type(ename) != markdown.MarkupName { | ||||||
| 		ext := strings.ToUpper(filepath.Ext(ename)) | 		ext := strings.ToUpper(filepath.Ext(ename)) | ||||||
| 		ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext) | 		ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext) | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user