all repos — grayfriday @ ca4bf013e8b5aee5850fe592db7bcc9a6032c5f8

blackfriday fork with a few changes

Merge pull request #284 from russross/fix-lint

Fix most of lint errors on v2
Vytautas Šaltenis vytas@rtfb.lt
Thu, 28 Jul 2016 19:45:39 +0300
commit

ca4bf013e8b5aee5850fe592db7bcc9a6032c5f8

parent

ce05617fea9bde4667ddc1bb8ceefe9d2a00ee5d

9 files changed, 142 insertions(+), 107 deletions(-)

jump to
M block.goblock.go

@@ -22,13 +22,13 @@ "github.com/shurcooL/sanitized_anchor_name"

) const ( - Entity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" - Escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" + charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" + escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" ) var ( reBackslashOrAmp = regexp.MustCompile("[\\&]") - reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + Escapable + "|" + Entity) + reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity) reTrailingWhitespace = regexp.MustCompile("(\n *)+$") )

@@ -279,9 +279,8 @@ i := skipChar(data, 1, '=')

i = skipChar(data, i, ' ') if data[i] == '\n' { return 1 - } else { - return 0 } + return 0 } // test of level 2 header

@@ -290,9 +289,8 @@ i := skipChar(data, 1, '-')

i = skipChar(data, i, ' ') if data[i] == '\n' { return 2 - } else { - return 0 } + return 0 } return 0

@@ -414,20 +412,20 @@ end := i

for end > 0 && data[end-1] == '\n' { end-- } - finalizeHtmlBlock(p.addBlock(HTMLBlock, data[:end])) + finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) } return i } -func finalizeHtmlBlock(block *Node) { +func finalizeHTMLBlock(block *Node) { block.Literal = reTrailingWhitespace.ReplaceAll(block.content, []byte{}) block.content = []byte{} } // HTML comment, lax form func (p *parser) htmlComment(data []byte, doRender bool) int { - i := p.inlineHtmlComment(data) + i := p.inlineHTMLComment(data) // needs to end with a blank line if j := p.isEmpty(data[i:]); j > 0 { size := i + j

@@ -438,7 +436,7 @@ for end > 0 && data[end-1] == '\n' {

end-- } block := p.addBlock(HTMLBlock, data[:end]) - finalizeHtmlBlock(block) + finalizeHTMLBlock(block) } return size }

@@ -470,7 +468,7 @@ end := size

for end > 0 && data[end-1] == '\n' { end-- } - finalizeHtmlBlock(p.addBlock(HTMLBlock, data[:end])) + finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) } return size }

@@ -729,9 +727,8 @@

func unescapeString(str []byte) []byte { if reBackslashOrAmp.Match(str) { return reEntityOrEscapedChar.ReplaceAllFunc(str, unescapeChar) - } else { - return str } + return str } func finalizeCodeBlock(block *Node) {
M block_test.goblock_test.go

@@ -1572,7 +1572,7 @@ `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> - <meta name="GENERATOR" content="Blackfriday Markdown Processor v1.4" /> + <meta name="GENERATOR" content="Blackfriday Markdown Processor v2.0" /> <meta charset="utf-8" /> </head> <body>
M helpers_test.gohelpers_test.go

@@ -54,7 +54,7 @@ func doTests(t *testing.T, tests []string) {

doTestsParam(t, tests, TestParams{ Options: DefaultOptions, HTMLRendererParameters: HTMLRendererParameters{ - Flags: CommonHtmlFlags, + Flags: CommonHTMLFlags, Extensions: CommonExtensions, }, })

@@ -106,7 +106,7 @@ doTestsInlineParam(t, transformTests, TestParams{

HTMLRendererParameters: params, }) doTestsInlineParam(t, transformTests, TestParams{ - HTMLFlags: CommonHtmlFlags, + HTMLFlags: CommonHTMLFlags, HTMLRendererParameters: params, }) }
M html.gohtml.go

@@ -24,6 +24,7 @@ "regexp"

"strings" ) +// HTMLFlags control optional behavior of HTML renderer. type HTMLFlags int // HTML renderer configuration options.

@@ -63,6 +64,8 @@ var (

htmlTagRe = regexp.MustCompile("(?i)^" + HTMLTag) ) +// HTMLRendererParameters is a collection of supplementary parameters tweaking +// the behavior of various parts of HTML renderer. type HTMLRendererParameters struct { // Prepend this text to each relative URL. AbsolutePrefix string

@@ -126,8 +129,8 @@ headerIDs: make(map[string]int),

} } -func isHtmlTag(tag []byte, tagname string) bool { - found, _ := findHtmlTagPos(tag, tagname) +func isHTMLTag(tag []byte, tagname string) bool { + found, _ := findHTMLTagPos(tag, tagname) return found }

@@ -154,7 +157,7 @@ }

return start } -func findHtmlTagPos(tag []byte, tagname string) (bool, int) { +func findHTMLTagPos(tag []byte, tagname string) (bool, int) { i := 0 if i < len(tag) && tag[0] != '<' { return false, -1

@@ -384,6 +387,16 @@ r.out(w, []byte{'\n'})

} } +// RenderNode is a default renderer of a single node of a syntax tree. For +// block nodes it will be called twice: first time with entering=true, second +// time with entering=false, so that it could know when it's working on an open +// tag and when on close. It writes the result to w. +// +// The return value is a way to tell the calling walker to adjust its walk +// pattern: e.g. it can terminate the traversal by returning Terminate. Or it +// can ask the walker to skip a subtree of this node by returning SkipChildren. +// The typical behavior is to return GoToNext, which asks for the usual +// traversal to the next node. func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkStatus { attrs := []string{} switch node.Type {

@@ -420,7 +433,7 @@ case HTMLSpan:

if r.Flags&SkipHTML != 0 { break } - if r.Flags&SkipStyle != 0 && isHtmlTag(node.Literal, "style") { + if r.Flags&SkipStyle != 0 && isHTMLTag(node.Literal, "style") { break } //if options.safe {

@@ -714,7 +727,7 @@ w.Write(esc([]byte(r.Title)))

} w.WriteString("</title>\n") w.WriteString(" <meta name=\"GENERATOR\" content=\"Blackfriday Markdown Processor v") - w.WriteString(VERSION) + w.WriteString(Version) w.WriteString("\"") w.WriteString(ending) w.WriteString(">\n")

@@ -739,6 +752,7 @@ }

w.WriteString("\n</body>\n</html>\n") } +// Render walks the specified syntax (sub)tree and returns a HTML document. func (r *HTMLRenderer) Render(ast *Node) []byte { //println("render_Blackfriday") //dump(ast)
M inline.goinline.go

@@ -266,13 +266,13 @@ t = linkDeferredFootnote

// ![alt] == image case offset >= 0 && data[offset] == '!': t = linkImg - offset += 1 + offset++ // ^[text] == inline footnote // [^refId] == deferred footnote case p.flags&Footnotes != 0: if offset >= 0 && data[offset] == '^' { t = linkInlineFootnote - offset += 1 + offset++ } else if len(data)-1 > offset && data[offset+1] == '^' { t = linkDeferredFootnote }

@@ -285,7 +285,7 @@ data = data[offset:]

var ( i = 1 - noteId int + noteID int title, link, altContent []byte textHasNl = false )

@@ -501,7 +501,7 @@ }

if t == linkInlineFootnote { // create a new reference - noteId = len(p.notes) + 1 + noteID = len(p.notes) + 1 var fragment []byte if len(id) > 0 {

@@ -512,11 +512,11 @@ fragment = make([]byte, 16)

} copy(fragment, slugify(id)) } else { - fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteId))...) + fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...) } ref := &reference{ - noteId: noteId, + noteID: noteID, hasBlock: false, link: fragment, title: id,

@@ -534,7 +534,7 @@ return 0

} if t == linkDeferredFootnote { - lr.noteId = len(p.notes) + 1 + lr.noteID = len(p.notes) + 1 p.notes = append(p.notes, lr) }

@@ -542,7 +542,7 @@ // keep link and title from reference

link = lr.link // if inline footnote, title == footnote contents title = lr.title - noteId = lr.noteId + noteID = lr.noteID } // rewind the whitespace

@@ -590,13 +590,13 @@ linkNode.Destination = uLink

linkNode.Title = title p.currBlock.appendChild(linkNode) linkNode.appendChild(text(data[1:txtE])) - i += 1 + i++ case linkInlineFootnote, linkDeferredFootnote: linkNode := NewNode(Link) linkNode.Destination = link linkNode.Title = title - linkNode.NoteID = noteId + linkNode.NoteID = noteID p.currBlock.appendChild(linkNode) if t == linkInlineFootnote { i++

@@ -609,7 +609,7 @@

return i } -func (p *parser) inlineHtmlComment(data []byte) int { +func (p *parser) inlineHTMLComment(data []byte) int { if len(data) < 5 { return 0 }

@@ -643,7 +643,7 @@ func leftAngle(p *parser, data []byte, offset int) int {

data = data[offset:] altype := LinkTypeNotAutolink end := tagLength(data, &altype) - if size := p.inlineHtmlComment(data); size > 0 { + if size := p.inlineHTMLComment(data); size > 0 { end = size } if end > 2 {

@@ -1026,9 +1026,8 @@

case '>': if nb == 1 { return i + 1 - } else { - return 0 } + return 0 default: return 0 }

@@ -1091,9 +1090,8 @@ }

if data[i] != '[' && data[i] != '(' { // not a link if tmpI > 0 { return tmpI - } else { - continue } + continue } cc := data[i] i++

@@ -1218,17 +1216,15 @@ // double symbol found, hand over to emph1

length = helperEmphasis(p, origData[offset-2:], c) if length == 0 { return 0 - } else { - return length - 2 } + return length - 2 default: // single symbol found, hand over to emph2 length = helperDoubleEmphasis(p, origData[offset-1:], c) if length == 0 { return 0 - } else { - return length - 1 } + return length - 1 } } return 0
M latex.golatex.go

@@ -311,7 +311,7 @@ r.w.WriteString(" urlcolor=black,%\n")

r.w.WriteString(" pdfstartview=FitH,%\n") r.w.WriteString(" breaklinks=true,%\n") r.w.WriteString(" pdfauthor={Blackfriday Markdown Processor v") - r.w.WriteString(VERSION) + r.w.WriteString(Version) r.w.WriteString("}}\n") r.w.WriteString("\n") r.w.WriteString("\\newcommand{\\HRule}{\\rule{\\linewidth}{0.5mm}}\n")
M markdown.gomarkdown.go

@@ -13,7 +13,7 @@ // Markdown parsing and processing

// // -// Blackfriday markdown processor. +// Package blackfriday is a markdown processor. // // Translates plain text with simple formatting rules into HTML or LaTeX. package blackfriday

@@ -26,8 +26,11 @@ "strings"

"unicode/utf8" ) -const VERSION = "1.4" +// Version string of the package. +const Version = "2.0" +// Extensions is a bitwise or'ed collection of enabled Blackfriday's +// extensions. type Extensions int // These are the supported markdown parsing extensions.

@@ -58,7 +61,7 @@ SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering

TOC // Generate a table of contents OmitContents // Skip the main contents (for a standalone table of contents) - CommonHtmlFlags HTMLFlags = UseXHTML + CommonHTMLFlags HTMLFlags = UseXHTML CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode | Autolink | Strikethrough | SpaceHeaders | HeaderIDs |

@@ -66,10 +69,13 @@ BackslashLineBreak | DefinitionLists | Smartypants |

SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes ) +// DefaultOptions is a convenience variable with all the options that are +// enabled by default. var DefaultOptions = Options{ Extensions: CommonExtensions, } +// TODO: this should probably be unexported. Or moved to node.go type LinkType int // These are the possible flag values for the link renderer.

@@ -81,6 +87,7 @@ LinkTypeNormal

LinkTypeEmail ) +// ListType contains bitwise or'ed flags for list and list item objects. type ListType int // These are the possible flag values for the ListItem renderer.

@@ -96,6 +103,7 @@ ListItemBeginningOfList

ListItemEndOfList ) +// CellAlignFlags holds a type of alignment in a table cell. type CellAlignFlags int // These are the possible flag values for the table cell renderer.

@@ -213,7 +221,7 @@ }

return &reference{ link: []byte(r.Link), title: []byte(r.Title), - noteId: 0, + noteID: 0, hasBlock: false, text: []byte(r.Text)}, true }

@@ -312,9 +320,8 @@ // set up the parser

return Markdown(input, renderer, Options{}) } -// Call Markdown with most useful extensions enabled -// MarkdownCommon is a convenience function for simple rendering. -// It processes markdown input with common extensions enabled, including: +// MarkdownCommon is a convenience function for simple rendering. It calls +// Markdown with most useful extensions enabled, including: // // * Smartypants processing with smart fractions and LaTeX dashes //

@@ -334,7 +341,7 @@ // * Custom Header IDs

func MarkdownCommon(input []byte) []byte { // set up the HTML renderer renderer := NewHTMLRenderer(HTMLRendererParameters{ - Flags: CommonHtmlFlags, + Flags: CommonHTMLFlags, Extensions: CommonExtensions, }) return Markdown(input, renderer, DefaultOptions)

@@ -354,6 +361,10 @@ }

return renderer.Render(Parse(input, options)) } +// Parse is an entry point to the parsing part of Blackfriday. It takes an +// input markdown document and produces a syntax tree for its contents. This +// tree can then be rendered with a default or custom renderer, or +// analyzed/transformed by the caller to whatever non-standard needs they have. func Parse(input []byte, opts Options) *Node { extensions := opts.Extensions

@@ -488,7 +499,7 @@ if p.flags&Footnotes == 0 || len(p.notes) == 0 {

return } p.tip = p.doc - finalizeHtmlBlock(p.addBlock(HTMLBlock, []byte(`<div class="footnotes">`))) + finalizeHTMLBlock(p.addBlock(HTMLBlock, []byte(`<div class="footnotes">`))) p.addBlock(HorizontalRule, nil) block := p.addBlock(List, nil) block.ListFlags = ListTypeOrdered

@@ -514,7 +525,7 @@ }

above := block.Parent finalizeList(block) p.tip = above - finalizeHtmlBlock(p.addBlock(HTMLBlock, []byte("</div>"))) + finalizeHTMLBlock(p.addBlock(HTMLBlock, []byte("</div>"))) block.Walk(func(node *Node, entering bool) WalkStatus { if node.Type == Paragraph || node.Type == Header { p.currBlock = node

@@ -592,7 +603,7 @@ p.block(input)

if p.flags&Footnotes != 0 && len(p.notes) > 0 { flags := ListItemBeginningOfList - for i := 0; i < len(p.notes); i += 1 { + for i := 0; i < len(p.notes); i++ { ref := p.notes[i] if ref.hasBlock { flags |= ListItemContainsBlock

@@ -642,14 +653,14 @@ // References are parsed and stored in this struct.

type reference struct { link []byte title []byte - noteId int // 0 if not a footnote ref + noteID int // 0 if not a footnote ref hasBlock bool text []byte } func (r *reference) String() string { - return fmt.Sprintf("{link: %q, title: %q, text: %q, noteId: %d, hasBlock: %v}", - r.link, r.title, r.text, r.noteId, r.hasBlock) + return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}", + r.link, r.title, r.text, r.noteID, r.hasBlock) } // Check whether or not data starts with a reference link.

@@ -667,7 +678,7 @@ for i < 3 && data[i] == ' ' {

i++ } - noteId := 0 + noteID := 0 // id part: anything but a newline between brackets if data[i] != '[' {

@@ -678,7 +689,7 @@ if p.flags&Footnotes != 0 {

if i < len(data) && data[i] == '^' { // we can set it to anything here because the proper noteIds will // be assigned later during the second pass. It just has to be != 0 - noteId = 1 + noteID = 1 i++ } }

@@ -721,7 +732,7 @@ raw []byte

hasBlock bool ) - if p.flags&Footnotes != 0 && noteId != 0 { + if p.flags&Footnotes != 0 && noteID != 0 { linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize) lineEnd = linkEnd } else {

@@ -734,11 +745,11 @@

// a valid ref has been found ref := &reference{ - noteId: noteId, + noteID: noteID, hasBlock: hasBlock, } - if noteId > 0 { + if noteID > 0 { // reusing the link field for the id since footnotes don't have links ref.link = data[idOffset:idEnd] // if footnote, it's not really a title, it's the contained text
M node.gonode.go

@@ -5,8 +5,12 @@ "bytes"

"fmt" ) +// NodeType specifies a type of a single node of a syntax tree. Usually one +// node (and its type) corresponds to a single markdown feature, e.g. emphasis +// or code block. type NodeType int +// Constants for identifying different types of nodes. See NodeType. const ( Document NodeType = iota BlockQuote

@@ -65,6 +69,7 @@ func (t NodeType) String() string {

return nodeTypeNames[t] } +// ListData contains fields relevant to a List node type. type ListData struct { ListFlags ListType Tight bool // Skip <p>s around list item data if true

@@ -73,12 +78,14 @@ Delimiter byte // '.' or ')' after the number in ordered lists

RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering } +// LinkData contains fields relevant to a Link node type. type LinkData struct { Destination []byte Title []byte NoteID int } +// CodeBlockData contains fields relevant to a CodeBlock node type. type CodeBlockData struct { IsFenced bool // Specifies whether it's a fenced code block or an indented one Info []byte // This holds the info string

@@ -87,11 +94,13 @@ FenceLength int

FenceOffset int } +// TableCellData contains fields relevant to a TableCell node type. type TableCellData struct { IsHeader bool // This tells if it's under the header row Align CellAlignFlags // This holds the value for align attribute } +// HeaderData contains fields relevant to a Header node type. type HeaderData struct { Level int // This holds the heading level number HeaderID string // This might hold header ID, if present

@@ -111,16 +120,17 @@ Next *Node // Next sibling; nil if it's the last child

Literal []byte // Text contents of the leaf nodes - HeaderData // Populated if Type == Header - ListData // Populated if Type == List - CodeBlockData // Populated if Type == CodeBlock - LinkData // Populated if Type == Link - TableCellData // Populated if Type == TableCell + HeaderData // Populated if Type is Header + ListData // Populated if Type is List + CodeBlockData // Populated if Type is CodeBlock + LinkData // Populated if Type is Link + TableCellData // Populated if Type is TableCell content []byte // Markdown content of the block nodes open bool // Specifies an open block node that has not been finished to process yet } +// NewNode allocates a node of a specified type. func NewNode(typ NodeType) *Node { return &Node{ Type: typ,

@@ -218,7 +228,6 @@ return true

default: return false } - return false } func (n *Node) canContain(t NodeType) bool {

@@ -246,9 +255,12 @@ // decide which node to go to next.

type WalkStatus int const ( - GoToNext WalkStatus = iota // The default traversal of every node. - SkipChildren // Skips all children of current node. - Terminate // Terminates the traversal. + // GoToNext is the default traversal of every node. + GoToNext WalkStatus = iota + // SkipChildren tells walker to skip all children of current node. + SkipChildren + // Terminate tells walker to terminate the traversal. + Terminate ) // NodeVisitor is a callback to be called when traversing the syntax tree.

@@ -256,8 +268,10 @@ // Called twice for every node: once with entering=true when the branch is

// first visited, then with entering=false after all the children are done. type NodeVisitor func(node *Node, entering bool) WalkStatus -func (root *Node) Walk(visitor NodeVisitor) { - walker := NewNodeWalker(root) +// Walk is a convenience method that instantiates a walker and starts a +// traversal of subtree rooted at n. +func (n *Node) Walk(visitor NodeVisitor) { + walker := newNodeWalker(n) node, entering := walker.next() for node != nil { status := visitor(node, entering)

@@ -272,21 +286,21 @@ }

} } -type NodeWalker struct { +type nodeWalker struct { current *Node root *Node entering bool } -func NewNodeWalker(root *Node) *NodeWalker { - return &NodeWalker{ +func newNodeWalker(root *Node) *nodeWalker { + return &nodeWalker{ current: root, root: nil, entering: true, } } -func (nw *NodeWalker) next() (*Node, bool) { +func (nw *nodeWalker) next() (*Node, bool) { if nw.current == nil { return nil, false }

@@ -314,7 +328,7 @@ }

return nw.current, nw.entering } -func (nw *NodeWalker) resumeAt(node *Node, entering bool) (*Node, bool) { +func (nw *nodeWalker) resumeAt(node *Node, entering bool) (*Node, bool) { nw.current = node nw.entering = entering return nw.next()

@@ -324,7 +338,7 @@ func dump(ast *Node) {

fmt.Println(dumpString(ast)) } -func dump_r(ast *Node, depth int) string { +func dumpR(ast *Node, depth int) string { if ast == nil { return "" }

@@ -335,11 +349,11 @@ content = ast.content

} result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content) for n := ast.FirstChild; n != nil; n = n.Next { - result += dump_r(n, depth+1) + result += dumpR(n, depth+1) } return result } func dumpString(ast *Node) string { - return dump_r(ast, 0) + return dumpR(ast, 0) }
M smartypants.gosmartypants.go

@@ -19,6 +19,7 @@ import (

"bytes" ) +// SPRenderer is a struct containing state of a Smartypants renderer. type SPRenderer struct { inSingleQuote bool inDoubleQuote bool

@@ -108,7 +109,7 @@ out.WriteString("quo;")

return true } -func (smrt *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { if len(text) >= 2 { t1 := tolower(text[1])

@@ -117,7 +118,7 @@ nextChar := byte(0)

if len(text) >= 3 { nextChar = text[2] } - if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote) { return 1 } }

@@ -142,7 +143,7 @@ nextChar := byte(0)

if len(text) > 1 { nextChar = text[1] } - if smartQuoteHelper(out, previousChar, nextChar, 's', &smrt.inSingleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote) { return 0 }

@@ -150,7 +151,7 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int { if len(text) >= 3 { t1 := tolower(text[1]) t2 := tolower(text[2])

@@ -175,7 +176,7 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int { if len(text) >= 2 { if text[1] == '-' { out.WriteString("&mdash;")

@@ -192,7 +193,7 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int { if len(text) >= 3 && text[1] == '-' && text[2] == '-' { out.WriteString("&mdash;") return 2

@@ -206,13 +207,13 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { +func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { if bytes.HasPrefix(text, []byte("&quot;")) { nextChar := byte(0) if len(text) >= 7 { nextChar = text[6] } - if smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote) { return 5 } }

@@ -225,15 +226,15 @@ out.WriteByte('&')

return 0 } -func (smrt *SPRenderer) smartAmp(out *bytes.Buffer, previousChar byte, text []byte) int { - return smrt.smartAmpVariant(out, previousChar, text, 'd') +func (r *SPRenderer) smartAmp(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartAmpVariant(out, previousChar, text, 'd') } -func (smrt *SPRenderer) smartAmpAngledQuote(out *bytes.Buffer, previousChar byte, text []byte) int { - return smrt.smartAmpVariant(out, previousChar, text, 'a') +func (r *SPRenderer) smartAmpAngledQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartAmpVariant(out, previousChar, text, 'a') } -func (smrt *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int { if len(text) >= 3 && text[1] == '.' && text[2] == '.' { out.WriteString("&hellip;") return 2

@@ -248,13 +249,13 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int { if len(text) >= 2 && text[1] == '`' { nextChar := byte(0) if len(text) >= 3 { nextChar = text[2] } - if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote) { + if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote) { return 1 } }

@@ -263,7 +264,7 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int { if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { // is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b // note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8)

@@ -305,7 +306,7 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int { if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { if text[0] == '1' && text[1] == '/' && text[2] == '2' { if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' {

@@ -333,27 +334,27 @@ out.WriteByte(text[0])

return 0 } -func (smrt *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { +func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { nextChar := byte(0) if len(text) > 1 { nextChar = text[1] } - if !smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote) { + if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote) { out.WriteString("&quot;") } return 0 } -func (smrt *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { - return smrt.smartDoubleQuoteVariant(out, previousChar, text, 'd') +func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartDoubleQuoteVariant(out, previousChar, text, 'd') } -func (smrt *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { - return smrt.smartDoubleQuoteVariant(out, previousChar, text, 'a') +func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartDoubleQuoteVariant(out, previousChar, text, 'a') } -func (smrt *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int { +func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int { i := 0 for i < len(text) && text[i] != '>' {

@@ -366,6 +367,7 @@ }

type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int +// NewSmartypantsRenderer constructs a Smartypants renderer object. func NewSmartypantsRenderer(flags Extensions) *SPRenderer { var r SPRenderer if flags&SmartypantsAngledQuotes == 0 {

@@ -398,13 +400,14 @@ r.callbacks['`'] = r.smartBacktick

return &r } -func (sr *SPRenderer) Process(text []byte) []byte { +// Process is the entry point of the Smartypants renderer. +func (r *SPRenderer) Process(text []byte) []byte { var buff bytes.Buffer // first do normal entity escaping text = esc(text) mark := 0 for i := 0; i < len(text); i++ { - if action := sr.callbacks[text[i]]; action != nil { + if action := r.callbacks[text[i]]; action != nil { if i > mark { buff.Write(text[mark:i]) }