From 126228d14621d21c7f7f86f009511b007b336f6e Mon Sep 17 00:00:00 2001 From: Unknwon Date: Fri, 20 Nov 2015 05:37:51 -0500 Subject: [PATCH] HTML render fix --- modules/base/markdown.go | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/modules/base/markdown.go b/modules/base/markdown.go index d55e98dd5..53eee4b3e 100644 --- a/modules/base/markdown.go +++ b/modules/base/markdown.go @@ -14,6 +14,7 @@ import ( "regexp" "strings" + "github.com/Unknwon/com" "github.com/russross/blackfriday" "golang.org/x/net/html" @@ -99,13 +100,26 @@ func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte, options.Renderer.Link(out, link, title, content) } +var ( + svgSuffix = []byte(".svg") + svgSuffixWithMark = []byte(".svg?") +) + func (options *CustomRender) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { prefix := strings.Replace(options.urlPrefix, "/src/", "/raw/", 1) - if len(link) > 0 && !isLink(link) { - if link[0] != '/' { - prefix += "/" + if len(link) > 0 { + if isLink(link) { + // External link with .svg suffix usually means CI status. + if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) { + options.Renderer.Image(out, link, title, alt) + return + } + } else { + if link[0] != '/' { + prefix += "/" + } + link = []byte(prefix + string(link)) } - link = []byte(prefix + string(link)) } out.WriteString(`") ) +var noEndTags = []string{"img", "input", "br", "hr"} + // PostProcessMarkdown treats different types of HTML differently, // and only renders special links for plain text blocks. func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte { - var startTag string + startTags := make([]string, 0, 5) var buf bytes.Buffer tokenizer := html.NewTokenizer(bytes.NewReader(rawHtml)) + +OUTER_LOOP: for html.ErrorToken != tokenizer.Next() { token := tokenizer.Token() switch token.Type { @@ -249,26 +267,32 @@ func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte { buf.Write(RenderSpecialLink([]byte(token.String()), urlPrefix)) case html.StartTagToken: - startTag = token.Data buf.WriteString(token.String()) tagName := token.Data // If this is an excluded tag, we skip processing all output until a close tag is encountered. if strings.EqualFold("a", tagName) || strings.EqualFold("code", tagName) || strings.EqualFold("pre", tagName) { for html.ErrorToken != tokenizer.Next() { token = tokenizer.Token() + // Copy the token to the output verbatim buf.WriteString(token.String()) // If this is the close tag, we are done - if html.EndTagToken == token.Type && strings.EqualFold(tagName, token.Data) { + if token.Type == html.EndTagToken && strings.EqualFold(tagName, token.Data) { break } } + continue OUTER_LOOP + } + + if !com.IsSliceContainsStr(noEndTags, token.Data) { + startTags = append(startTags, token.Data) } case html.EndTagToken: buf.Write(leftAngleBracket) - buf.WriteString(startTag) + buf.WriteString(startTags[len(startTags)-1]) buf.Write(rightAngleBracket) + startTags = startTags[:len(startTags)-1] default: buf.WriteString(token.String()) }