HTML render fix

This commit is contained in:
Unknwon 2015-11-20 05:37:51 -05:00
parent 74dfe439c2
commit 126228d146

View File

@ -14,6 +14,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/Unknwon/com"
"github.com/russross/blackfriday" "github.com/russross/blackfriday"
"golang.org/x/net/html" "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) 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) { func (options *CustomRender) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
prefix := strings.Replace(options.urlPrefix, "/src/", "/raw/", 1) prefix := strings.Replace(options.urlPrefix, "/src/", "/raw/", 1)
if len(link) > 0 && !isLink(link) { if len(link) > 0 {
if link[0] != '/' { if isLink(link) {
prefix += "/" // 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(`<a href="`) out.WriteString(`<a href="`)
@ -236,12 +250,16 @@ var (
rightAngleBracket = []byte(">") rightAngleBracket = []byte(">")
) )
var noEndTags = []string{"img", "input", "br", "hr"}
// PostProcessMarkdown treats different types of HTML differently, // PostProcessMarkdown treats different types of HTML differently,
// and only renders special links for plain text blocks. // and only renders special links for plain text blocks.
func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte { func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte {
var startTag string startTags := make([]string, 0, 5)
var buf bytes.Buffer var buf bytes.Buffer
tokenizer := html.NewTokenizer(bytes.NewReader(rawHtml)) tokenizer := html.NewTokenizer(bytes.NewReader(rawHtml))
OUTER_LOOP:
for html.ErrorToken != tokenizer.Next() { for html.ErrorToken != tokenizer.Next() {
token := tokenizer.Token() token := tokenizer.Token()
switch token.Type { switch token.Type {
@ -249,26 +267,32 @@ func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte {
buf.Write(RenderSpecialLink([]byte(token.String()), urlPrefix)) buf.Write(RenderSpecialLink([]byte(token.String()), urlPrefix))
case html.StartTagToken: case html.StartTagToken:
startTag = token.Data
buf.WriteString(token.String()) buf.WriteString(token.String())
tagName := token.Data tagName := token.Data
// If this is an excluded tag, we skip processing all output until a close tag is encountered. // 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) { if strings.EqualFold("a", tagName) || strings.EqualFold("code", tagName) || strings.EqualFold("pre", tagName) {
for html.ErrorToken != tokenizer.Next() { for html.ErrorToken != tokenizer.Next() {
token = tokenizer.Token() token = tokenizer.Token()
// Copy the token to the output verbatim // Copy the token to the output verbatim
buf.WriteString(token.String()) buf.WriteString(token.String())
// If this is the close tag, we are done // 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 break
} }
} }
continue OUTER_LOOP
}
if !com.IsSliceContainsStr(noEndTags, token.Data) {
startTags = append(startTags, token.Data)
} }
case html.EndTagToken: case html.EndTagToken:
buf.Write(leftAngleBracket) buf.Write(leftAngleBracket)
buf.WriteString(startTag) buf.WriteString(startTags[len(startTags)-1])
buf.Write(rightAngleBracket) buf.Write(rightAngleBracket)
startTags = startTags[:len(startTags)-1]
default: default:
buf.WriteString(token.String()) buf.WriteString(token.String())
} }