all repos — grayfriday @ cf97fbd89772bdcef0e088d38e9ce4ecb261ea15

blackfriday fork with a few changes

experiment: render headers directly to output buffer to avoid a copy; minor speed boost
Russ Ross russ@russross.com
Sat, 25 Jun 2011 08:20:08 -0600
commit

cf97fbd89772bdcef0e088d38e9ce4ecb261ea15

parent

45ab8d0dc4470fdfdf90a48ebbccb3c8924ebbb1

4 files changed, 34 insertions(+), 15 deletions(-)

jump to
M block.goblock.go

@@ -186,10 +186,12 @@ for end > 0 && (data[end-1] == ' ' || data[end-1] == '\t') {

end-- } if end > i { - var work bytes.Buffer - parseInline(&work, rndr, data[i:end]) if rndr.mk.Header != nil { - rndr.mk.Header(out, work.Bytes(), level, rndr.mk.Opaque) + work := func() bool { + parseInline(out, rndr, data[i:end]) + return true + } + rndr.mk.Header(out, work, level, rndr.mk.Opaque) } } return skip

@@ -1071,9 +1073,14 @@ // render the paragraph

renderParagraph(out, rndr, data[:prev]) // render the header - var work bytes.Buffer - parseInline(&work, rndr, data[prev:i-1]) - rndr.mk.Header(out, work.Bytes(), level, rndr.mk.Opaque) + // this ugly, convoluted closure avoids forcing variables onto the heap + work := func(o *bytes.Buffer, r *render, d []byte) func() bool { + return func() bool { + parseInline(o, r, d) + return true + } + }(out, rndr, data[prev:i-1]) + rndr.mk.Header(out, work, level, rndr.mk.Opaque) // find the end of the underline for ; i < len(data) && data[i] != '\n'; i++ {
M html.gohtml.go

@@ -163,10 +163,11 @@ out.Write(src[org:])

} } -func htmlHeader(out *bytes.Buffer, text []byte, level int, opaque interface{}) { +func htmlHeader(out *bytes.Buffer, text func() bool, level int, opaque interface{}) { options := opaque.(*htmlOptions) + marker := out.Len() - if out.Len() > 0 { + if marker > 0 { out.WriteByte('\n') }

@@ -177,7 +178,10 @@ } else {

out.WriteString(fmt.Sprintf("<h%d>", level)) } - out.Write(text) + if !text() { + out.Truncate(marker) + return + } out.WriteString(fmt.Sprintf("</h%d>\n", level)) }

@@ -572,8 +576,10 @@ func htmlNormalText(out *bytes.Buffer, text []byte, opaque interface{}) {

attrEscape(out, text) } -func htmlTocHeader(out *bytes.Buffer, text []byte, level int, opaque interface{}) { +func htmlTocHeader(out *bytes.Buffer, text func() bool, level int, opaque interface{}) { options := opaque.(*htmlOptions) + marker := out.Len() + for level > options.tocData.currentLevel { if options.tocData.currentLevel > 0 { out.WriteString("<li>")

@@ -595,8 +601,9 @@ out.WriteString(strconv.Itoa(options.tocData.headerCount))

out.WriteString("\">") options.tocData.headerCount++ - if len(text) > 0 { - out.Write(text) + if !text() { + out.Truncate(marker) + return } out.WriteString("</a></li>\n") }
M latex.golatex.go

@@ -76,7 +76,9 @@ }

//BlockHtml func(out *bytes.Buffer, text []byte, opaque interface{}) -func latexHeader(out *bytes.Buffer, text []byte, level int, opaque interface{}) { +func latexHeader(out *bytes.Buffer, text func() bool, level int, opaque interface{}) { + marker := out.Len() + switch level { case 1: out.WriteString("\n\\section{")

@@ -91,7 +93,10 @@ out.WriteString("\n\\subparagraph{")

case 6: out.WriteString("\n\\textbf{") } - out.Write(text) + if !text() { + out.Truncate(marker) + return + } out.WriteString("}\n") }
M markdown.gomarkdown.go

@@ -99,7 +99,7 @@ // block-level callbacks---nil skips the block

BlockCode func(out *bytes.Buffer, text []byte, lang string, opaque interface{}) BlockQuote func(out *bytes.Buffer, text []byte, opaque interface{}) BlockHtml func(out *bytes.Buffer, text []byte, opaque interface{}) - Header func(out *bytes.Buffer, text []byte, level int, opaque interface{}) + Header func(out *bytes.Buffer, text func() bool, level int, opaque interface{}) HRule func(out *bytes.Buffer, opaque interface{}) List func(out *bytes.Buffer, text []byte, flags int, opaque interface{}) ListItem func(out *bytes.Buffer, text []byte, flags int, opaque interface{})