esc.go (view raw)
1package blackfriday
2
3import (
4 "html"
5 "io"
6)
7
8var htmlEscaper = [256][]byte{
9 '&': []byte("&"),
10 '<': []byte("<"),
11 '>': []byte(">"),
12 '"': []byte("""),
13}
14
15func escapeHTML(w io.Writer, s []byte) {
16 var start, end int
17 for end < len(s) {
18 escSeq := htmlEscaper[s[end]]
19 if escSeq != nil {
20 isEntity, entityEnd := nodeIsEntity(s, end)
21 if isEntity {
22 w.Write(s[start : entityEnd+1])
23 start = entityEnd + 1
24 } else {
25 w.Write(s[start:end])
26 w.Write(escSeq)
27 start = end + 1
28 }
29 }
30 end++
31 }
32 if start < len(s) && end <= len(s) {
33 w.Write(s[start:end])
34 }
35}
36
37func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) {
38 isEntity = false
39 endEntityPos = end + 1
40
41 if s[end] == '&' {
42 for endEntityPos < len(s) {
43 if s[endEntityPos] == ';' {
44 isEntity = true
45 break
46 }
47 if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' {
48 break
49 }
50 endEntityPos++
51 }
52 }
53
54 return isEntity, endEntityPos
55}
56
57func escLink(w io.Writer, text []byte) {
58 unesc := html.UnescapeString(string(text))
59 escapeHTML(w, []byte(unesc))
60}