export EscapeHTML

This commit is contained in:
Krzysztof Kowalczyk 2018-01-27 00:52:23 -08:00
parent f96b8484da
commit 0b8b77db40
3 changed files with 20 additions and 18 deletions

16
esc.go
View File

@ -12,23 +12,25 @@ var htmlEscaper = [256][]byte{
'"': []byte("""), '"': []byte("""),
} }
func escapeHTML(w io.Writer, s []byte) { // EscapeHTML writes html-escaped d to w. It escapes &, <, > and " characters.
func EscapeHTML(w io.Writer, d []byte) {
var start, end int var start, end int
for end < len(s) { n := len(d)
escSeq := htmlEscaper[s[end]] for end < n {
escSeq := htmlEscaper[d[end]]
if escSeq != nil { if escSeq != nil {
w.Write(s[start:end]) w.Write(d[start:end])
w.Write(escSeq) w.Write(escSeq)
start = end + 1 start = end + 1
} }
end++ end++
} }
if start < len(s) && end <= len(s) { if start < n && end <= n {
w.Write(s[start:end]) w.Write(d[start:end])
} }
} }
func escLink(w io.Writer, text []byte) { func escLink(w io.Writer, text []byte) {
unesc := html.UnescapeString(string(text)) unesc := html.UnescapeString(string(text))
escapeHTML(w, []byte(unesc)) EscapeHTML(w, []byte(unesc))
} }

View File

@ -16,7 +16,7 @@ func TestEsc(t *testing.T) {
} }
for i := 0; i < len(tests); i += 2 { for i := 0; i < len(tests); i += 2 {
var b bytes.Buffer var b bytes.Buffer
escapeHTML(&b, []byte(tests[i])) EscapeHTML(&b, []byte(tests[i]))
if !bytes.Equal(b.Bytes(), []byte(tests[i+1])) { if !bytes.Equal(b.Bytes(), []byte(tests[i+1])) {
t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]", t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]",
tests[i], tests[i+1], b.String()) tests[i], tests[i+1], b.String())
@ -42,7 +42,7 @@ func BenchmarkEscapeHTML(b *testing.B) {
var buf bytes.Buffer var buf bytes.Buffer
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
for _, t := range tests { for _, t := range tests {
escapeHTML(&buf, t) EscapeHTML(&buf, t)
buf.Reset() buf.Reset()
} }
} }

View File

@ -418,13 +418,13 @@ func (r *HTMLRenderer) outHRTag(w io.Writer) {
func (r *HTMLRenderer) text(w io.Writer, node *Node, nodeData *TextData) { func (r *HTMLRenderer) text(w io.Writer, node *Node, nodeData *TextData) {
if r.params.Flags&Smartypants != 0 { if r.params.Flags&Smartypants != 0 {
var tmp bytes.Buffer var tmp bytes.Buffer
escapeHTML(&tmp, node.Literal) EscapeHTML(&tmp, node.Literal)
r.sr.Process(w, tmp.Bytes()) r.sr.Process(w, tmp.Bytes())
} else { } else {
if isLinkData(node.Parent.Data) { if isLinkData(node.Parent.Data) {
escLink(w, node.Literal) escLink(w, node.Literal)
} else { } else {
escapeHTML(w, node.Literal) EscapeHTML(w, node.Literal)
} }
} }
} }
@ -476,7 +476,7 @@ func (r *HTMLRenderer) linkEnter(w io.Writer, node *Node, nodeData *LinkData) {
if len(nodeData.Title) > 0 { if len(nodeData.Title) > 0 {
var titleBuff bytes.Buffer var titleBuff bytes.Buffer
titleBuff.WriteString("title=\"") titleBuff.WriteString("title=\"")
escapeHTML(&titleBuff, nodeData.Title) EscapeHTML(&titleBuff, nodeData.Title)
titleBuff.WriteByte('"') titleBuff.WriteByte('"')
attrs = append(attrs, titleBuff.String()) attrs = append(attrs, titleBuff.String())
} }
@ -523,7 +523,7 @@ func (r *HTMLRenderer) imageExit(w io.Writer, node *Node, nodeData *ImageData) {
if r.disableTags == 0 { if r.disableTags == 0 {
if nodeData.Title != nil { if nodeData.Title != nil {
r.outs(w, `" title="`) r.outs(w, `" title="`)
escapeHTML(w, nodeData.Title) EscapeHTML(w, nodeData.Title)
} }
r.outs(w, `" />`) r.outs(w, `" />`)
} }
@ -571,7 +571,7 @@ func (r *HTMLRenderer) image(w io.Writer, node *Node, nodeData *ImageData, enter
func (r *HTMLRenderer) code(w io.Writer, node *Node, nodeData *CodeData) { func (r *HTMLRenderer) code(w io.Writer, node *Node, nodeData *CodeData) {
r.outs(w, "<code>") r.outs(w, "<code>")
escapeHTML(w, node.Literal) EscapeHTML(w, node.Literal)
r.outs(w, "</code>") r.outs(w, "</code>")
} }
@ -740,7 +740,7 @@ func (r *HTMLRenderer) codeBlock(w io.Writer, node *Node, nodeData *CodeBlockDat
r.cr(w) r.cr(w)
r.outs(w, "<pre>") r.outs(w, "<pre>")
r.outTag(w, "<code", attrs) r.outTag(w, "<code", attrs)
escapeHTML(w, node.Literal) EscapeHTML(w, node.Literal)
r.outs(w, "</code>") r.outs(w, "</code>")
r.outs(w, "</pre>") r.outs(w, "</pre>")
if !isListItemData(node.Parent.Data) { if !isListItemData(node.Parent.Data) {
@ -898,7 +898,7 @@ func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) {
if r.params.Flags&Smartypants != 0 { if r.params.Flags&Smartypants != 0 {
r.sr.Process(w, []byte(r.params.Title)) r.sr.Process(w, []byte(r.params.Title))
} else { } else {
escapeHTML(w, []byte(r.params.Title)) EscapeHTML(w, []byte(r.params.Title))
} }
io.WriteString(w, "</title>\n") io.WriteString(w, "</title>\n")
io.WriteString(w, " <meta name=\"GENERATOR\" content=\"Markdown Processor for Go v") io.WriteString(w, " <meta name=\"GENERATOR\" content=\"Markdown Processor for Go v")
@ -911,14 +911,14 @@ func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) {
io.WriteString(w, ">\n") io.WriteString(w, ">\n")
if r.params.CSS != "" { if r.params.CSS != "" {
io.WriteString(w, " <link rel=\"stylesheet\" type=\"text/css\" href=\"") io.WriteString(w, " <link rel=\"stylesheet\" type=\"text/css\" href=\"")
escapeHTML(w, []byte(r.params.CSS)) EscapeHTML(w, []byte(r.params.CSS))
io.WriteString(w, "\"") io.WriteString(w, "\"")
io.WriteString(w, ending) io.WriteString(w, ending)
io.WriteString(w, ">\n") io.WriteString(w, ">\n")
} }
if r.params.Icon != "" { if r.params.Icon != "" {
io.WriteString(w, " <link rel=\"icon\" type=\"image/x-icon\" href=\"") io.WriteString(w, " <link rel=\"icon\" type=\"image/x-icon\" href=\"")
escapeHTML(w, []byte(r.params.Icon)) EscapeHTML(w, []byte(r.params.Icon))
io.WriteString(w, "\"") io.WriteString(w, "\"")
io.WriteString(w, ending) io.WriteString(w, ending)
io.WriteString(w, ">\n") io.WriteString(w, ">\n")