all repos — grayfriday @ ea57e936666ea85a95e2de15ffe77cb547546380

blackfriday fork with a few changes

Several fixes after code review
Vytautas Ĺ altenis vytas@rtfb.lt
Thu, 02 Feb 2017 11:52:49 +0200
commit

ea57e936666ea85a95e2de15ffe77cb547546380

parent

120bb2fae155ccb71b20303046b7cee8e4bbc9c4

4 files changed, 44 insertions(+), 37 deletions(-)

jump to
M block.goblock.go

@@ -764,7 +764,7 @@ break

} // include the newline in data sent to tableRow - if i < len(data)-1 && data[i] == '\n' { + if i < len(data) && data[i] == '\n' { i++ } p.tableRow(data[rowStart:i], columns, false)

@@ -945,7 +945,7 @@ for i < 3 && i < len(data) && data[i] == ' ' {

i++ } if i < len(data) && data[i] == '>' { - if i < len(data)-1 && data[i+1] == ' ' { + if i+1 < len(data) && data[i+1] == ' ' { return i + 2 } return i + 1

@@ -1005,7 +1005,7 @@ }

// returns prefix length for block code func (p *parser) codePrefix(data []byte) int { - if data[0] == '\t' { + if len(data) >= 1 && data[0] == '\t' { return 1 } if len(data) >= 4 && data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' {

@@ -1073,7 +1073,7 @@ }

if i >= len(data)-1 { return 0 } - // need a *, +, or - followed by a space + // need one of {'*', '+', '-'} followed by a space or a tab if (data[i] != '*' && data[i] != '+' && data[i] != '-') || (data[i+1] != ' ' && data[i+1] != '\t') { return 0

@@ -1099,7 +1099,7 @@ if start == i || i >= len(data)-1 {

return 0 } - // we need >= 1 digits followed by a dot and a space + // we need >= 1 digits followed by a dot and a space or a tab if data[i] != '.' || !(data[i+1] == ' ' || data[i+1] == '\t') { return 0 }

@@ -1112,7 +1112,7 @@ if len(data) < 2 {

return 0 } i := 0 - // need a : followed by a spaces + // need a ':' followed by a space or a tab if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') { return 0 }

@@ -1194,11 +1194,12 @@ // Assumes initial prefix is already removed if this is a sublist.

func (p *parser) listItem(data []byte, flags *ListType) int { // keep track of the indentation of the first line itemIndent := 0 - if data[itemIndent] == '\t' { + if data[0] == '\t' { itemIndent += 4 - } - for itemIndent < 3 && data[itemIndent] == ' ' { - itemIndent++ + } else { + for itemIndent < 3 && data[itemIndent] == ' ' { + itemIndent++ + } } var bulletChar byte = '*'

@@ -1436,8 +1437,7 @@ if n := p.isEmpty(current); n > 0 {

// did this blank line followed by a definition list item? if p.flags&DefinitionLists != 0 { if i < len(data)-1 && data[i+1] == ':' { - ret := p.list(data[prev:], ListTypeDefinition) - return ret + return p.list(data[prev:], ListTypeDefinition) } }
M esc_test.goesc_test.go

@@ -38,11 +38,11 @@ []byte("Here's an inline [link](</script?foo=1&bar=2>)."),

[]byte("[1]: http://example.com/?foo=1&bar=2"), []byte("[2]: http://att.com/ \"AT&T\""), } - var buff bytes.Buffer + var buf bytes.Buffer for n := 0; n < b.N; n++ { for _, t := range tests { - escapeHTML(&buff, t) - buff.Reset() + escapeHTML(&buf, t) + buf.Reset() } } }
M html.gohtml.go

@@ -559,11 +559,11 @@ }

} else { if entering { dest = r.addAbsPrefix(dest) - var hrefBuff bytes.Buffer - hrefBuff.WriteString("href=\"") - escLink(&hrefBuff, dest) - hrefBuff.WriteByte('"') - attrs = append(attrs, hrefBuff.String()) + var hrefBuf bytes.Buffer + hrefBuf.WriteString("href=\"") + escLink(&hrefBuf, dest) + hrefBuf.WriteByte('"') + attrs = append(attrs, hrefBuf.String()) if node.NoteID != 0 { r.out(w, footnoteRef(r.FootnoteAnchorPrefix, node)) break

@@ -939,17 +939,17 @@ // Render walks the specified syntax (sub)tree and returns a HTML document.

func (r *HTMLRenderer) Render(ast *Node) []byte { //println("render_Blackfriday") //dump(ast) - var buff bytes.Buffer - r.writeDocumentHeader(&buff) + var buf bytes.Buffer + r.writeDocumentHeader(&buf) if r.Extensions&TOC != 0 || r.Extensions&OmitContents != 0 { - r.writeTOC(&buff, ast) + r.writeTOC(&buf, ast) if r.Extensions&OmitContents != 0 { - return buff.Bytes() + return buf.Bytes() } } ast.Walk(func(node *Node, entering bool) WalkStatus { - return r.RenderNode(&buff, node, entering) + return r.RenderNode(&buf, node, entering) }) - r.writeDocumentFooter(&buff) - return buff.Bytes() + r.writeDocumentFooter(&buf) + return buf.Bytes() }
M inline.goinline.go

@@ -715,14 +715,11 @@ entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1)

return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd } -var prefixes = [][]byte{ - []byte("http://"), - []byte("https://"), - []byte("ftp://"), - []byte("file://"), - []byte("mailto:"), -} - +// hasPrefixCaseInsensitive is a custom implementation of +// strings.HasPrefix(strings.ToLower(s), prefix) +// we rolled our own because ToLower pulls in a huge machinery of lowercasing +// anything from Unicode and that's very slow. Since this func will only be +// used on ASCII protocol prefixes, we can take shortcuts. func hasPrefixCaseInsensitive(s, prefix []byte) bool { if len(s) < len(prefix) { return false

@@ -736,12 +733,22 @@ }

return true } +var protocolPrefixes = [][]byte{ + []byte("http://"), + []byte("https://"), + []byte("ftp://"), + []byte("file://"), + []byte("mailto:"), +} + +const shortestPrefix = 6 // len("ftp://"), the shortest of the above + func maybeAutoLink(p *parser, data []byte, offset int) (int, *Node) { // quick check to rule out most false hits - if p.insideLink || len(data) < offset+6 { // 6 is the len() of the shortest of the prefixes + if p.insideLink || len(data) < offset+shortestPrefix { return 0, nil } - for _, prefix := range prefixes { + for _, prefix := range protocolPrefixes { endOfHead := offset + 8 // 8 is the len() of the longest prefix if endOfHead > len(data) { endOfHead = len(data)